Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ed77ea5ab | ||
|
|
de4e233884 | ||
|
|
55a99da2f5 | ||
|
|
6093d56c90 | ||
|
|
9cf4556b9d | ||
|
|
536ebf56cb | ||
|
|
3ad345519b | ||
|
|
dc587e493f | ||
|
|
f692ae2222 | ||
|
|
aa89ebdb93 | ||
|
|
198a4d74a5 | ||
|
|
3b5fe36717 | ||
|
|
03444ae4ff | ||
|
|
390bbdb6ec | ||
|
|
2bc7b62324 | ||
|
|
4376ee8908 | ||
|
|
195f0cfa40 | ||
|
|
ab61d8d5c0 | ||
|
|
aaf0b8e423 | ||
|
|
7e14846f0b | ||
|
|
5ebd133c63 | ||
|
|
563f1c588d | ||
|
|
6b612588c4 | ||
|
|
6ef113e821 | ||
|
|
c25f44c2a0 | ||
|
|
d039864dca | ||
|
|
a4f1f23d3c | ||
|
|
fe20fa4e99 | ||
|
|
5c30fd847a | ||
|
|
64de325678 | ||
|
|
489557c1a3 | ||
|
|
439fdfa12c | ||
|
|
f695dbf115 | ||
|
|
7c45b1e075 | ||
|
|
64453716b0 |
@@ -95,7 +95,6 @@ react-native.fs/unlink
|
||||
react-native.fs/file-exists?
|
||||
status-im.ui.components.colors/white
|
||||
status-im.ui.components.colors/black
|
||||
status-im.transport.core-test/messages
|
||||
status-im.ui.components.core/animated-header
|
||||
status-im.ui.components.core/safe-area-provider
|
||||
status-im.ui.components.core/safe-area-consumer
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{:linters
|
||||
{:unresolved-symbol
|
||||
{:exclude [(cljs.test/is [match? thrown-match?])
|
||||
(clojure.test/is [match? thrown-match?])]}}}
|
||||
@@ -32,6 +32,7 @@
|
||||
"letsubs" :binding
|
||||
"with-let" "let"
|
||||
"reg-event-fx" :arg1-pair
|
||||
"reg-fx" :arg1-pair
|
||||
"testing" :arg1-body
|
||||
"deftest-sub" :arg1-body
|
||||
"wait-for" :arg1-body
|
||||
|
||||
@@ -27,18 +27,23 @@ class StatusOkHttpClientFactory implements OkHttpClientFactory {
|
||||
X509Certificate cert = null;
|
||||
HandshakeCertificates clientCertificates;
|
||||
String certPem = "";
|
||||
// Get TLS PEM certificate from status-go
|
||||
try {
|
||||
// induce half second sleep because sometimes a cert is not immediately available
|
||||
// TODO : remove sleep if App no longer crashes on Android 10 devices with
|
||||
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
|
||||
Thread.sleep(500);
|
||||
certPem = getCertificatePem();
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Could not getImageTLSCert",e);
|
||||
}
|
||||
|
||||
// Get TLS PEM certificate from status-go
|
||||
try {
|
||||
// induce half second sleep because sometimes a cert is not immediately available
|
||||
// TODO : remove sleep if App no longer crashes on Android 10 devices with
|
||||
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
|
||||
Thread.sleep(500);
|
||||
certPem = StatusPackage.getImageTLSCert();
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Could not getImageTLSCert",e);
|
||||
}
|
||||
// Convert PEM certificate string to X509Certificate object
|
||||
if (certPem.isEmpty()) {
|
||||
Log.e(TAG, "Certificate is empty, cannot create OkHttpClient without a valid certificate");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert PEM certificate string to X509Certificate object
|
||||
try {
|
||||
// induce half second sleep because sometimes a cert is not immediately available
|
||||
// TODO : remove sleep if App no longer crashes on Android 10 devices
|
||||
@@ -74,4 +79,17 @@ class StatusOkHttpClientFactory implements OkHttpClientFactory {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private String getCertificatePem() {
|
||||
try {
|
||||
String certPem = StatusPackage.getImageTLSCert();
|
||||
if (certPem == null || certPem.trim().isEmpty()) {
|
||||
Log.e(TAG, "Certificate PEM string is null or empty");
|
||||
return "";
|
||||
}
|
||||
return certPem;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not getImageTLSCert", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,6 +641,26 @@ keywords and concatenating them into a single string.
|
||||
```
|
||||
|
||||
### Tests
|
||||
#### Prefer `match?` over `=` when comparing data structures
|
||||
|
||||
Prefer the `match?` directive over `=` when comparing data structures, otherwise
|
||||
when the check fails the output can be too difficult to read. `match?` is
|
||||
defined by library https://github.com/nubank/matcher-combinators.
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
(deftest some-test
|
||||
(let [expected {...}
|
||||
actual {...}]
|
||||
(is (= expected actual))))
|
||||
|
||||
;; good
|
||||
(deftest some-test
|
||||
(let [expected {...}
|
||||
actual {...}]
|
||||
(is (match? expected actual))))
|
||||
```
|
||||
|
||||
#### Subscription tests
|
||||
|
||||
Test [layer-3 subscriptions](https://day8.github.io/re-frame/subscriptions/) by
|
||||
|
||||
@@ -602,6 +602,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd",
|
||||
"sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/apache/ant/ant/1.10.11/ant-1.10.11",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -746,6 +755,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"jar": {
|
||||
"sha1": "aa95d25ea98bfe1152ea540f6e58a303c8cacc86",
|
||||
"sha256": "0qvdsr5ryjmrpz622ivpyq5aayn42y4bk531vbasyj2yj7gcg35h"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
|
||||
@@ -65,6 +65,7 @@ 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
|
||||
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
|
||||
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar
|
||||
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
|
||||
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
|
||||
org/babashka/sci/0.7.38/sci-0.7.38.jar
|
||||
@@ -81,6 +82,7 @@ org/clojure/data.json/2.4.0/data.json-2.4.0.jar
|
||||
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/math.combinatorics/0.2.0/math.combinatorics-0.2.0.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
|
||||
|
||||
@@ -14,6 +14,7 @@ stdenv.mkDerivation {
|
||||
"patchJavaPhase"
|
||||
"patchReactNativePhase"
|
||||
"patchPodPhase"
|
||||
"patchGlogPhase"
|
||||
"installPhase"
|
||||
];
|
||||
|
||||
@@ -98,6 +99,14 @@ stdenv.mkDerivation {
|
||||
'[RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];'
|
||||
'';
|
||||
|
||||
# Fix pod issue after upgrading to MacOS Sonoma and Xcode 15
|
||||
# https://github.com/status-im/status-mobile/issues/17682
|
||||
patchGlogPhase = ''
|
||||
substituteInPlace ./node_modules/react-native/scripts/ios-configure-glog.sh \
|
||||
--replace 'export CC="' '#export CC="' \
|
||||
--replace 'export CXX="' '#export CXX="'
|
||||
'';
|
||||
|
||||
# The ELF types are incompatible with the host platform, so let's not even try
|
||||
# TODO: Use Android NDK to strip binaries manually
|
||||
dontPatchELF = true;
|
||||
|
||||
@@ -73,6 +73,7 @@ in {
|
||||
allowHigher = true;
|
||||
};
|
||||
go = super.go_1_19;
|
||||
clang = super.clang_15;
|
||||
buildGoPackage = super.buildGo119Package;
|
||||
buildGoModule = super.buildGo119Module;
|
||||
gomobile = (super.gomobile.overrideAttrs (old: {
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@
|
||||
"process": "0.11.10",
|
||||
"react-test-renderer": "18.0.0",
|
||||
"rn-snoopy": "git+https://github.com/status-im/rn-snoopy.git#refs/tags/v2.0.2-status",
|
||||
"shadow-cljs": "2.25.0"
|
||||
"shadow-cljs": "2.26.2"
|
||||
},
|
||||
"binary": {
|
||||
"module_name": "status_nodejs_addon",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 851 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
+4
-2
@@ -12,10 +12,12 @@
|
||||
[metosin/malli "0.13.0"]
|
||||
|
||||
;; Dev dependencies
|
||||
[refactor-nrepl "2.5.0"]
|
||||
[cider/cider-nrepl "0.25.3"]
|
||||
[refactor-nrepl "3.9.1"]
|
||||
[cider/cider-nrepl "0.31.0"]
|
||||
[cider/piggieback "0.4.1"]
|
||||
[org.slf4j/slf4j-nop "2.0.9"]
|
||||
[re-frisk-remote "1.6.0"]
|
||||
[nubank/matcher-combinators "3.8.8"]
|
||||
|
||||
;; Use the same version specified in the Nix dependency.
|
||||
[clj-kondo/clj-kondo "2023.09.07"]
|
||||
|
||||
@@ -118,13 +118,61 @@
|
||||
"M2.79504 9.01494C2.89473 8.85584 3.00297 8.70977 3.11963 8.5761C3.90594 7.67512 4.97212 7.45024 5.99992 7.45024C7.02772 7.45024 8.0939 7.67512 8.88021 8.5761C8.99688 8.70978 9.10512 8.85585 9.2048 9.01495C8.9501 9.28561 8.66149 9.52401 8.34577 9.72335C8.25403 9.55824 8.15512 9.41818 8.05145 9.29939C7.56503 8.74204 6.88121 8.55024 5.99992 8.55024C5.11862 8.55024 4.43481 8.74204 3.94839 9.29939C3.84472 9.41818 3.74582 9.55824 3.65408 9.72334C3.33835 9.524 3.04975 9.2856 2.79504 9.01494ZM5.99992 3.5502C5.47525 3.5502 5.04992 3.97552 5.04992 4.5002C5.04992 5.02487 5.47525 5.4502 5.99992 5.4502C6.52459 5.4502 6.94992 5.02487 6.94992 4.5002C6.94992 3.97552 6.52459 3.5502 5.99992 3.5502ZM3.94992 4.5002C3.94992 3.36801 4.86773 2.4502 5.99992 2.4502C7.1321 2.4502 8.04992 3.36801 8.04992 4.5002C8.04992 5.63238 7.1321 6.5502 5.99992 6.5502C4.86773 6.5502 3.94992 5.63238 3.94992 4.5002Z"
|
||||
:fill color-2}]])
|
||||
|
||||
(defn- contact-20
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/circle
|
||||
{:cx 10
|
||||
:cy 10
|
||||
:r 7.5
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M8.65002 7.99998C8.65002 7.25439 9.25443 6.64998 10 6.64998C10.7456 6.64998 11.35 7.25439 11.35 7.99998C11.35 8.74556 10.7456 9.34998 10 9.34998C9.25443 9.34998 8.65002 8.74556 8.65002 7.99998ZM10 5.34998C8.53646 5.34998 7.35002 6.53642 7.35002 7.99998C7.35002 9.46353 8.53646 10.65 10 10.65C11.4636 10.65 12.65 9.46353 12.65 7.99998C12.65 6.53642 11.4636 5.34998 10 5.34998ZM10 13.65C8.67557 13.65 7.53064 14.4186 6.98692 15.5341C6.60094 15.3235 6.23942 15.0737 5.90771 14.79C6.69408 13.3369 8.23179 12.35 10 12.35C11.7682 12.35 13.306 13.3369 14.0923 14.79C13.7606 15.0737 13.3991 15.3235 13.0131 15.5341C12.4694 14.4186 11.3245 13.65 10 13.65Z"
|
||||
:fill color-2}]])
|
||||
|
||||
(defn- verified-20
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d
|
||||
"M18 10C18 8.77003 17.1118 7.74751 15.9418 7.53891C16.6216 6.56407 16.5267 5.21294 15.6569 4.34321C14.7872 3.47344 13.436 3.37852 12.4611 4.05845C12.2526 2.88834 11.23 2 10 2C8.77 2 7.74747 2.88827 7.53889 4.05832C6.56406 3.37846 5.21292 3.47339 4.34318 4.34313C3.47343 5.21288 3.3785 6.56404 4.05839 7.53888C2.88831 7.74743 2 8.76998 2 10C2 11.23 2.88824 12.2525 4.05826 12.4611C3.3784 13.4359 3.47333 14.7871 4.34307 15.6568C5.21284 16.5266 6.56403 16.6215 7.53887 15.9416C7.74741 17.1117 8.76996 18 10 18C11.23 18 12.2525 17.1117 12.4611 15.9417C13.4359 16.6215 14.7871 16.5266 15.6568 15.6569C16.5265 14.7871 16.6215 13.436 15.9416 12.4611C17.1117 12.2526 18 11.23 18 10Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d "M7.25 10.75L9.25 12.25L12.75 7.75"
|
||||
:stroke color-2
|
||||
:stroke-width "1.2"}]])
|
||||
|
||||
(defn- untrustworthy-20
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d "M10 2L15.6569 4.34315L18 10L15.6569 15.6569L10 18L4.34315 15.6569L2 10L4.34315 4.34315L10 2Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M10.75 5.5L10.55 11.5H9.45L9.25 5.5H10.75ZM10 13C10.4142 13 10.75 13.3358 10.75 13.75C10.75 14.1642 10.4142 14.5 10 14.5C9.58579 14.5 9.25 14.1642 9.25 13.75C9.25 13.3358 9.58579 13 10 13Z"
|
||||
:fill color-2}]])
|
||||
|
||||
(def ^:private icons
|
||||
{:i/clear-20 clear-20
|
||||
:i/dropdown-20 dropdown-20
|
||||
:i/pullup-20 pullup-20
|
||||
:i/dropdown-12 dropdown-12
|
||||
:i/pullup-12 pullup-12
|
||||
:i/contact-12 contact-12})
|
||||
{:i/clear-20 clear-20
|
||||
:i/dropdown-20 dropdown-20
|
||||
:i/pullup-20 pullup-20
|
||||
:i/dropdown-12 dropdown-12
|
||||
:i/pullup-12 pullup-12
|
||||
:i/contact-12 contact-12
|
||||
:i/contact-20 contact-20
|
||||
:i/verified-20 verified-20
|
||||
:i/untrustworthy-20 untrustworthy-20})
|
||||
|
||||
(defn- append-to-keyword
|
||||
[k & xs]
|
||||
|
||||
@@ -61,14 +61,10 @@
|
||||
value (reagent/atom "")
|
||||
focused? (atom false)]
|
||||
(fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan on-detect-ens
|
||||
on-detect-address
|
||||
ens-regex address-regex
|
||||
valid-ens-or-address?]}]
|
||||
on-detect-address address-regex valid-ens-or-address?]}]
|
||||
(let [on-change (fn [text]
|
||||
(when (not= @value text)
|
||||
(let [ens? (when ens-regex
|
||||
(boolean (re-matches ens-regex text)))
|
||||
address? (when address-regex
|
||||
(let [address? (when address-regex
|
||||
(boolean (re-matches address-regex text)))]
|
||||
(if (> (count text) 0)
|
||||
(reset! status :typing)
|
||||
@@ -76,9 +72,9 @@
|
||||
(reset! value text)
|
||||
(when on-change-text
|
||||
(on-change-text text))
|
||||
(when (and ens? on-detect-ens)
|
||||
(when (and on-detect-ens (> (count text) 0))
|
||||
(reset! status :loading)
|
||||
(on-detect-ens text))
|
||||
(on-detect-ens text #(reset! status :typing)))
|
||||
(when (and address? on-detect-address)
|
||||
(reset! status :loading)
|
||||
(on-detect-address text)))))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
(ns quo.components.text-combinations.username.component-spec
|
||||
(:require [quo.components.text-combinations.username.view :as username]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn test-all-status
|
||||
[component-to-render component-props]
|
||||
(h/test "Verified status"
|
||||
(h/render [component-to-render (assoc component-props :status :verified)])
|
||||
(h/is-truthy (h/get-by-label-text :username-status-icon)))
|
||||
|
||||
(h/test "Contact status"
|
||||
(h/render [component-to-render (assoc component-props :status :contact)])
|
||||
(h/is-truthy (h/get-by-label-text :username-status-icon)))
|
||||
|
||||
(h/test "Untrustworthy status"
|
||||
(h/render [component-to-render (assoc component-props :status :untrustworthy)])
|
||||
(h/is-truthy (h/get-by-label-text :username-status-icon)))
|
||||
|
||||
(h/test "Untrustworthy contact status"
|
||||
(h/render [component-to-render (assoc component-props :status :untrustworthy-contact)])
|
||||
(let [icons (h/get-all-by-label-text :username-status-icon)]
|
||||
(h/is-truthy (aget icons 0))
|
||||
(h/is-truthy (aget icons 1))))
|
||||
|
||||
(h/test "Blocked status"
|
||||
(h/render [component-to-render (assoc component-props :status :blocked)])
|
||||
(h/is-truthy (h/get-by-label-text :username-status-icon))))
|
||||
|
||||
(h/describe "Text combinations - Username"
|
||||
(h/test "Renders default"
|
||||
(h/render [username/view {:username "Test username"}])
|
||||
(h/is-truthy (h/get-by-text "Test username")))
|
||||
|
||||
(h/describe "Render different :name-type values"
|
||||
(h/describe "default"
|
||||
(let [props {:name-type :default
|
||||
:username "Test username"}]
|
||||
|
||||
(h/test "default render"
|
||||
(h/render [username/view props])
|
||||
(h/is-truthy (h/get-by-text "Test username")))
|
||||
|
||||
(h/describe "All status are rendered"
|
||||
(test-all-status username/view props))))
|
||||
|
||||
(h/describe "ens"
|
||||
(let [props {:name-type :ens
|
||||
:username "test-username.eth"}]
|
||||
|
||||
(h/test "no status render"
|
||||
(h/render [username/view props])
|
||||
(h/is-truthy (h/get-by-text "test-username.eth")))
|
||||
|
||||
(h/describe "All status are rendered"
|
||||
(test-all-status username/view props))))
|
||||
|
||||
(h/describe "nickname"
|
||||
(let [props {:name-type :nickname
|
||||
:username "Nickname"
|
||||
:name "Real name"}]
|
||||
|
||||
(h/test "no status render"
|
||||
(h/render [username/view props])
|
||||
(h/is-truthy (h/get-by-text "Nickname"))
|
||||
(h/is-truthy (h/get-by-text "Real name")))
|
||||
|
||||
(h/describe "All status are rendered"
|
||||
(test-all-status username/view props))))))
|
||||
@@ -0,0 +1,30 @@
|
||||
(ns quo.components.text-combinations.username.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:height 32})
|
||||
|
||||
(def username-text-container
|
||||
{:flex-direction :row
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn real-name-text
|
||||
[theme blur?]
|
||||
{:color (if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
|
||||
(colors/theme-colors colors/neutral-60 colors/neutral-40 theme))})
|
||||
|
||||
(defn real-name-dot
|
||||
[theme blur?]
|
||||
(assoc (real-name-text theme blur?) :margin-horizontal 6))
|
||||
|
||||
(defn status-icon-container
|
||||
[name-type status]
|
||||
(cond-> {:flex-direction :row
|
||||
:margin-left 4}
|
||||
(#{:default :ens} name-type) (assoc :margin-top 8
|
||||
:margin-bottom 4)
|
||||
(= :nickname name-type) (assoc :margin-top 10
|
||||
:margin-bottom 2)
|
||||
(= status :untrustworthy-contact) (assoc :margin-right 2)))
|
||||
@@ -0,0 +1,57 @@
|
||||
(ns quo.components.text-combinations.username.view
|
||||
(:require [quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.text-combinations.username.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- username-text
|
||||
[{:keys [theme name-type username blur?]
|
||||
real-name :name}]
|
||||
[rn/view {:style style/username-text-container}
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold}
|
||||
username]
|
||||
(when (= name-type :nickname)
|
||||
[:<>
|
||||
[text/text
|
||||
{:style (style/real-name-dot theme blur?)
|
||||
:size :paragraph-1
|
||||
:weight :medium}
|
||||
"∙"]
|
||||
[text/text
|
||||
{:style (style/real-name-text theme blur?)
|
||||
:size :paragraph-1
|
||||
:weight :medium}
|
||||
real-name]])])
|
||||
|
||||
(defn- icon-20
|
||||
[icon-name theme color]
|
||||
[icon/icon icon-name
|
||||
{:accessibility-label :username-status-icon
|
||||
:size 20
|
||||
:color (colors/resolve-color color theme)}])
|
||||
|
||||
(defn status-icon
|
||||
[{:keys [theme name-type status]
|
||||
:or {name-type :default}}]
|
||||
[rn/view {:style (style/status-icon-container name-type status)}
|
||||
(case status
|
||||
:verified [icon-20 :i/verified theme :success]
|
||||
:contact [icon-20 :i/contact theme :blue]
|
||||
:untrustworthy [icon-20 :i/untrustworthy theme :danger]
|
||||
:blocked [icon-20 :i/block theme :danger]
|
||||
:untrustworthy-contact [:<>
|
||||
[icon-20 :i/untrustworthy theme :danger]
|
||||
[icon-20 :i/contact theme :blue]]
|
||||
nil)])
|
||||
|
||||
(defn view-internal
|
||||
[props]
|
||||
[rn/view {:style style/container}
|
||||
[username-text props]
|
||||
[status-icon props]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,99 @@
|
||||
(ns quo.components.wallet.confirmation-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- get-test-data
|
||||
[{:keys [state network]
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:counter (reagent/atom 0)
|
||||
:total-box 85
|
||||
:progress-value "10"
|
||||
:network network
|
||||
:state state
|
||||
:customization-color :blue})
|
||||
|
||||
(h/describe "Confirmation Progress"
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box))))
|
||||
@@ -0,0 +1,9 @@
|
||||
(ns quo.components.wallet.confirmation-progress.style)
|
||||
|
||||
(def progress-box-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-bottom 10
|
||||
:padding-top 4
|
||||
:flex-wrap :wrap})
|
||||
@@ -0,0 +1,69 @@
|
||||
(ns quo.components.wallet.confirmation-progress.view
|
||||
(:require [quo.components.wallet.confirmation-progress.style :as style]
|
||||
[quo.components.wallet.progress-bar.view :as progress-box]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private max-progress 100)
|
||||
(def ^:private min-progress 0)
|
||||
|
||||
(defn- calculate-box-state
|
||||
[state counter index]
|
||||
(cond
|
||||
(and (= state :sending) (>= counter index) (< index 3)) :confirmed
|
||||
(and (= state :confirmed) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalising) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalising) (>= counter index) (> index 4) (< index 20)) :finalized
|
||||
(and (= state :finalized) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalized) (>= counter index) (> index 4)) :finalized
|
||||
(and (= state :error) (>= counter index) (< index 2)) :error
|
||||
:else :pending))
|
||||
|
||||
(defn- calculate-box-state-sidenet
|
||||
[state]
|
||||
(case state
|
||||
:error :error
|
||||
(:confirmed :finalising :finalized) :finalized
|
||||
:pending))
|
||||
|
||||
(defn- calculate-progressed-value
|
||||
[state progress-value]
|
||||
(case state
|
||||
:finalising progress-value
|
||||
:finalized max-progress
|
||||
min-progress))
|
||||
|
||||
(defn- progress-boxes-mainnet
|
||||
[{:keys [state counter total-box]}]
|
||||
[rn/view
|
||||
{:accessibility-label :mainnet-progress-box
|
||||
:style style/progress-box-container}
|
||||
(let [numbers (range 1 total-box)]
|
||||
(doall (for [n numbers]
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state state counter n)
|
||||
:customization-color :blue
|
||||
:key n}])))])
|
||||
|
||||
(defn- progress-boxes-sidenet
|
||||
[{:keys [state progress-value]}]
|
||||
[rn/view
|
||||
{:accessibility-label :progress-box
|
||||
:style style/progress-box-container}
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state-sidenet state)
|
||||
:customization-color :success}]
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state-sidenet state)
|
||||
:full-width? true
|
||||
:progressed-value (calculate-progressed-value state progress-value)
|
||||
:customization-color :blue}]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [network] :as props}]
|
||||
(case network
|
||||
:mainnet [progress-boxes-mainnet props]
|
||||
(:arbitrum :optimism) [progress-boxes-sidenet props]
|
||||
nil))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -39,7 +39,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "finalized state with customtization-color blue in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -51,7 +51,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 60)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "finalized state with customtization-color army in light mode"
|
||||
(let [theme :light
|
||||
@@ -63,7 +63,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "confirmed state in light mode"
|
||||
(let [theme :light
|
||||
@@ -75,7 +75,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor colors/success-50})))
|
||||
:backgroundColor (colors/resolve-color :success theme)})))
|
||||
|
||||
(h/test "confirmed state in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -99,7 +99,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor colors/danger-50})))
|
||||
:backgroundColor (colors/resolve-color :danger theme)})))
|
||||
|
||||
(h/test "error state in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -111,4 +111,4 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/white-opa-5
|
||||
:backgroundColor colors/danger-60}))))
|
||||
:backgroundColor (colors/resolve-color :danger theme)}))))
|
||||
|
||||
@@ -3,31 +3,48 @@
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn- border-and-background-color
|
||||
[customization-color]
|
||||
[customization-color theme]
|
||||
{:light {:pending {:border-color colors/neutral-80-opa-5
|
||||
:background-color colors/neutral-5}
|
||||
:confirmed {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color :success 50)}
|
||||
:background-color (colors/resolve-color :success theme)}
|
||||
:finalized {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color customization-color 50)}
|
||||
:background-color (colors/resolve-color customization-color theme)}
|
||||
:error {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color :danger 50)}}
|
||||
:background-color (colors/resolve-color :danger theme)}}
|
||||
:dark {:pending {:border-color colors/neutral-70
|
||||
:background-color colors/neutral-80}
|
||||
:confirmed {:border-color colors/white-opa-5
|
||||
:background-color (colors/custom-color :success 60)}
|
||||
:background-color (colors/resolve-color :success theme)}
|
||||
:finalized {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color customization-color 60)}
|
||||
:background-color (colors/resolve-color customization-color theme)}
|
||||
:error {:border-color colors/white-opa-5
|
||||
:background-color (colors/custom-color :danger 60)}}})
|
||||
:background-color (colors/resolve-color :danger theme)}}})
|
||||
|
||||
(def max-value 100)
|
||||
|
||||
(defn root-container
|
||||
[{:keys [customization-color state theme]}]
|
||||
(let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color)
|
||||
[theme state])]
|
||||
[{:keys [customization-color state theme full-width?]}]
|
||||
(let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color
|
||||
theme)
|
||||
[theme (if full-width? :pending state)])]
|
||||
{:height 12
|
||||
:flex (when full-width? 1)
|
||||
:width (when (not full-width?) 8)
|
||||
:border-radius 3
|
||||
:border-width 1
|
||||
:border-color border-color
|
||||
:background-color background-color
|
||||
:margin-horizontal 1
|
||||
:margin-vertical 2}))
|
||||
|
||||
(defn progressed-bar
|
||||
[{:keys [customization-color state theme progressed-value]}]
|
||||
(let [{:keys [background-color]} (get-in (border-and-background-color customization-color theme)
|
||||
[theme state])
|
||||
progress (if (> progressed-value max-value) max-value progressed-value)]
|
||||
{:height 12
|
||||
:width 8
|
||||
:margin-top -1
|
||||
:width (str progress "%")
|
||||
:border-radius 3
|
||||
:border-width 1
|
||||
:border-color border-color
|
||||
:background-color background-color}))
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- view-internal
|
||||
[props]
|
||||
[{:keys [full-width?] :as props}]
|
||||
[rn/view
|
||||
{:accessibility-label :progress-bar
|
||||
:style (style/root-container props)}])
|
||||
:style (style/root-container props)}
|
||||
(when full-width?
|
||||
[rn/view {:style (style/progressed-bar props)}])])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
(defn container
|
||||
[networks? theme]
|
||||
{:width 335
|
||||
{:width "100%"
|
||||
:height (if networks? 90 56)
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
(ns quo.components.wallet.transaction-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- get-test-data
|
||||
[{:keys [state network]
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:title "Title"
|
||||
:tag-name "Doodle"
|
||||
:tag-number "120"
|
||||
:network network
|
||||
:customization-color :blue
|
||||
:networks [{:network :mainnet
|
||||
:state state
|
||||
:counter (reagent/atom 0)
|
||||
:total-box 85
|
||||
:progress 30
|
||||
:epoch-number "123"}
|
||||
{:network :optimism
|
||||
:state state
|
||||
:progress "50"
|
||||
:epoch-number "123"}
|
||||
{:network :arbitrum
|
||||
:state state
|
||||
:progress "30"
|
||||
:epoch-number "123"}]
|
||||
:on-press (fn []
|
||||
(js/alert "Transaction progress item pressed"))})
|
||||
|
||||
(h/describe "Transaction Progress"
|
||||
(h/test "component renders without props"
|
||||
(h/render [quo/transaction-progress])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "mainnet progress box is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "arbitrum-optimism progress box is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "arbitrum progress box is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "optimism progress box is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "title is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "context tag is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag))))
|
||||
@@ -0,0 +1,38 @@
|
||||
(ns quo.components.wallet.transaction-progress.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def title-text-container
|
||||
{:flex 1})
|
||||
|
||||
(def icon
|
||||
{:margin-right 4})
|
||||
|
||||
(defn box-style
|
||||
[theme]
|
||||
{:border-radius 16
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)})
|
||||
|
||||
(def title-container
|
||||
{:align-items :center
|
||||
:flex-direction :row
|
||||
:padding-left 12
|
||||
:padding-top 8
|
||||
:padding-right 8
|
||||
:padding-bottom 4})
|
||||
|
||||
(def status-row-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex 1
|
||||
:padding-horizontal 12
|
||||
:padding-top 8
|
||||
:padding-bottom 4})
|
||||
|
||||
(defn context-tag-container
|
||||
[theme]
|
||||
{:padding-horizontal 12
|
||||
:padding-bottom 8
|
||||
:flex-direction :row
|
||||
:border-bottom-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)})
|
||||
@@ -0,0 +1,187 @@
|
||||
(ns quo.components.wallet.transaction-progress.view
|
||||
(:require [quo.components.buttons.button.view :as button]
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.context-tag.view :as context-tag]
|
||||
[quo.components.wallet.confirmation-progress.view :as confirmation-progress]
|
||||
[quo.components.wallet.transaction-progress.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ^:private max-mainnet-verifications 4)
|
||||
(def ^:private max-sidenet-verifications 1)
|
||||
|
||||
(defn- icon-internal
|
||||
([icon]
|
||||
(icon-internal icon nil 20))
|
||||
([icon color]
|
||||
(icon-internal icon color 20))
|
||||
([icon color size]
|
||||
[rn/view {:style style/icon}
|
||||
[icons/icon
|
||||
icon
|
||||
{:color color
|
||||
:size size
|
||||
:no-color (when (not color) true)}]]))
|
||||
|
||||
(defn- text-internal
|
||||
[{:keys [weight size accessibility-label color]
|
||||
:or {weight :semi-bold
|
||||
size :paragraph-1}}
|
||||
title]
|
||||
[text/text
|
||||
{:accessibility-label accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight weight
|
||||
:size size
|
||||
:style {:color color}}
|
||||
title])
|
||||
|
||||
(defn- network-type-text
|
||||
[state]
|
||||
(case state
|
||||
(:sending :pending) (i18n/label :t/pending-on)
|
||||
(:confirmed :finalising) (i18n/label :t/confirmed-on)
|
||||
:finalized (i18n/label :t/finalized-on)
|
||||
:error (i18n/label :t/failed-on)
|
||||
nil))
|
||||
|
||||
(defn- calculate-counter
|
||||
[counter]
|
||||
(if (< counter 4) counter max-mainnet-verifications))
|
||||
|
||||
(defn mainnet-label
|
||||
[counter]
|
||||
(str counter "/" max-mainnet-verifications))
|
||||
|
||||
(defn subnet-label
|
||||
[counter]
|
||||
(str counter "/" max-sidenet-verifications))
|
||||
|
||||
(defn- text-steps
|
||||
[network state epoch-number counter]
|
||||
(let [steps (case network
|
||||
:mainnet
|
||||
{:pending (mainnet-label 0)
|
||||
:sending (mainnet-label (calculate-counter counter))
|
||||
:confirmed (mainnet-label (calculate-counter counter))
|
||||
:finalising (mainnet-label (calculate-counter counter))
|
||||
:finalized (i18n/label :t/epoch-number {:number epoch-number})
|
||||
:error (mainnet-label 0)}
|
||||
(or :optimism :arbitrum)
|
||||
{:pending (subnet-label 0)
|
||||
:sending (subnet-label 0)
|
||||
:confirmed (subnet-label 0)
|
||||
:finalising (subnet-label 1)
|
||||
:finalized (i18n/label :t/epoch-number {:number epoch-number})
|
||||
:error (subnet-label 0)}
|
||||
nil)]
|
||||
(get steps state)))
|
||||
|
||||
(defn- get-status-icon
|
||||
[theme state]
|
||||
(case state
|
||||
(:pending :sending) {:icon :i/pending-state
|
||||
:color (colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}
|
||||
(:confirmed :finalising) {:icon :i/positive-state
|
||||
:color (colors/resolve-color :success theme)}
|
||||
:finalized {:icon :i/diamond}
|
||||
:error {:icon :i/negative-state
|
||||
:color (colors/resolve-color :danger theme)}
|
||||
nil))
|
||||
|
||||
(defn- get-network
|
||||
[networks network]
|
||||
(some #(when (= (:network %) network) %)
|
||||
networks))
|
||||
|
||||
(defn- calculate-error-state
|
||||
[networks]
|
||||
(some #(= (:state %) :error) networks))
|
||||
|
||||
(defn- title-internal
|
||||
[{:keys [title theme networks]}]
|
||||
[rn/view {:style style/title-container}
|
||||
[icon-internal :i/placeholder (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)]
|
||||
[rn/view {:style style/title-text-container}
|
||||
[text-internal nil title]]
|
||||
(when (calculate-error-state networks)
|
||||
[button/button
|
||||
{:size 24
|
||||
:icon-left :i/refresh}
|
||||
(i18n/label :t/retry)])])
|
||||
|
||||
(defn- tag-internal
|
||||
[tag-photo tag-name tag-number theme]
|
||||
[rn/view {:style (style/context-tag-container theme)}
|
||||
[context-tag/view
|
||||
{:size 24
|
||||
:collectible tag-photo
|
||||
:collectible-name tag-name
|
||||
:collectible-number tag-number
|
||||
:type :collectible}]])
|
||||
|
||||
(defn- get-network-text
|
||||
[network]
|
||||
(case network
|
||||
:arbitrum (i18n/label :t/arbitrum)
|
||||
:mainnet (i18n/label :t/mainnet)
|
||||
:optimism (i18n/label :t/optimism)
|
||||
nil))
|
||||
|
||||
(defn- status-row
|
||||
[{:keys [theme state network epoch-number counter]}]
|
||||
(let [{:keys [icon color]} (get-status-icon theme state)]
|
||||
[rn/view {:style style/status-row-container}
|
||||
[icon-internal icon color 16]
|
||||
[rn/view {:style style/title-text-container}
|
||||
[text-internal
|
||||
{:weight :regular
|
||||
:size :paragraph-2}
|
||||
(str (network-type-text state) " " (get-network-text network))]]
|
||||
[rn/view
|
||||
[text-internal
|
||||
{:weight :regular
|
||||
:size :paragraph-2
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}
|
||||
(text-steps network state epoch-number counter)]]]))
|
||||
|
||||
(defn- view-network
|
||||
[{:keys [theme state epoch-number counter total-box progress network]}]
|
||||
[:<>
|
||||
[status-row
|
||||
{:theme theme
|
||||
:state state
|
||||
:network network
|
||||
:epoch-number epoch-number
|
||||
:counter counter}]
|
||||
[confirmation-progress/view
|
||||
{:state state
|
||||
:network network
|
||||
:counter counter
|
||||
:total-box total-box
|
||||
:progress-value progress}]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [title on-press accessibility-label theme tag-photo tag-name tag-number networks]
|
||||
:or {accessibility-label :transaction-progress}}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view {:style (style/box-style theme)}
|
||||
[title-internal
|
||||
{:title title
|
||||
:theme theme
|
||||
:networks networks}]
|
||||
[tag-internal tag-photo tag-name tag-number theme]
|
||||
(for [network networks]
|
||||
^{:key (:network network)}
|
||||
(let [assoc-props #(get-network networks %)]
|
||||
[view-network (assoc-props (:network network))]))]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -141,11 +141,13 @@
|
||||
quo.components.tags.token-tag.view
|
||||
quo.components.text-combinations.channel-name.view
|
||||
quo.components.text-combinations.standard-title.view
|
||||
quo.components.text-combinations.username.view
|
||||
quo.components.text-combinations.view
|
||||
quo.components.wallet.account-card.view
|
||||
quo.components.wallet.account-origin.view
|
||||
quo.components.wallet.account-overview.view
|
||||
quo.components.wallet.address-text.view
|
||||
quo.components.wallet.confirmation-progress.view
|
||||
quo.components.wallet.keypair.view
|
||||
quo.components.wallet.network-amount.view
|
||||
quo.components.wallet.network-bridge.view
|
||||
@@ -154,6 +156,7 @@
|
||||
quo.components.wallet.progress-bar.view
|
||||
quo.components.wallet.summary-info.view
|
||||
quo.components.wallet.token-input.view
|
||||
quo.components.wallet.transaction-progress.view
|
||||
quo.components.wallet.transaction-summary.view
|
||||
quo.components.wallet.wallet-activity.view
|
||||
quo.components.wallet.wallet-overview.view))
|
||||
@@ -383,12 +386,14 @@
|
||||
(def channel-name quo.components.text-combinations.channel-name.view/view)
|
||||
(def standard-title quo.components.text-combinations.standard-title.view/view)
|
||||
(def text-combinations quo.components.text-combinations.view/view)
|
||||
(def username quo.components.text-combinations.username.view/view)
|
||||
|
||||
;;;; Wallet
|
||||
(def account-card quo.components.wallet.account-card.view/view)
|
||||
(def account-origin quo.components.wallet.account-origin.view/view)
|
||||
(def account-overview quo.components.wallet.account-overview.view/view)
|
||||
(def address-text quo.components.wallet.address-text.view/view)
|
||||
(def confirmation-propgress quo.components.wallet.confirmation-progress.view/view)
|
||||
(def keypair quo.components.wallet.keypair.view/view)
|
||||
(def network-amount quo.components.wallet.network-amount.view/view)
|
||||
(def network-bridge quo.components.wallet.network-bridge.view/view)
|
||||
@@ -399,4 +404,5 @@
|
||||
(def token-input quo.components.wallet.token-input.view/view)
|
||||
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
|
||||
(def wallet-activity quo.components.wallet.wallet-activity.view/view)
|
||||
(def transaction-progress quo.components.wallet.transaction-progress.view/view)
|
||||
(def transaction-summary quo.components.wallet.transaction-summary.view/view)
|
||||
|
||||
@@ -77,9 +77,11 @@
|
||||
[quo.components.tags.summary-tag.component-spec]
|
||||
[quo.components.tags.tiny-tag.component-spec]
|
||||
[quo.components.text-combinations.channel-name.component-spec]
|
||||
[quo.components.text-combinations.username.component-spec]
|
||||
[quo.components.wallet.account-card.component-spec]
|
||||
[quo.components.wallet.account-origin.component-spec]
|
||||
[quo.components.wallet.account-overview.component-spec]
|
||||
[quo.components.wallet.confirmation-progress.component-spec]
|
||||
[quo.components.wallet.keypair.component-spec]
|
||||
[quo.components.wallet.network-amount.component-spec]
|
||||
[quo.components.wallet.network-bridge.component-spec]
|
||||
@@ -87,6 +89,7 @@
|
||||
[quo.components.wallet.progress-bar.component-spec]
|
||||
[quo.components.wallet.summary-info.component-spec]
|
||||
[quo.components.wallet.token-input.component-spec]
|
||||
[quo.components.wallet.transaction-progress.component-spec]
|
||||
[quo.components.wallet.transaction-summary.component-spec]
|
||||
[quo.components.wallet.wallet-activity.component-spec]
|
||||
[quo.components.wallet.wallet-overview.component-spec]))
|
||||
|
||||
@@ -285,10 +285,6 @@
|
||||
(get-in colors-map [color suffix]))))
|
||||
|
||||
(defn- resolve-color*
|
||||
"(resolve-color color theme opacity)
|
||||
color hex string or keyword (resolves from custom, network and semantic colors)
|
||||
theme :light/:dark
|
||||
opacity 0-100 (optional) - if set theme is ignored and goes to 50 suffix internally"
|
||||
([color theme]
|
||||
(resolve-color* color theme nil))
|
||||
([color theme opacity]
|
||||
@@ -300,7 +296,12 @@
|
||||
suffix (get-from-colors-map suffix)
|
||||
opacity (alpha (/ opacity 100))))))
|
||||
|
||||
(def resolve-color (memoize resolve-color*))
|
||||
(def resolve-color
|
||||
"(resolve-color color theme opacity)
|
||||
color hex string or keyword (resolves from custom, network and semantic colors)
|
||||
theme :light/:dark
|
||||
opacity 0-100 (optional) - if set theme is ignored and goes to 50 suffix internally"
|
||||
(memoize resolve-color*))
|
||||
|
||||
(def ^{:deprecated true :superseded-by "resolve-color"}
|
||||
custom-color
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
[goog.object :as object]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.chat.models.message-content :as message-content]
|
||||
[status-im.data-store.messages :as data-store-messages]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.chat.composer.link-preview.events :as link-preview]
|
||||
[status-im2.contexts.chat.messages.transport.events :as messages.transport]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
@@ -205,7 +205,7 @@
|
||||
(rf/merge cofx
|
||||
(clean-input (:current-chat-id db))
|
||||
(link-preview/reset-unfurled)
|
||||
(chat.message/send-messages messages)))))
|
||||
(messages.transport/send-chat-messages messages)))))
|
||||
|
||||
(rf/defn send-audio-message
|
||||
[{:keys [db] :as cofx} audio-path duration current-chat-id]
|
||||
@@ -214,25 +214,26 @@
|
||||
(when-not (string/blank? audio-path)
|
||||
(rf/merge
|
||||
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :responding-to-message] nil)}
|
||||
(chat.message/send-message
|
||||
(merge
|
||||
{:chat-id current-chat-id
|
||||
:content-type constants/content-type-audio
|
||||
:audio-path audio-path
|
||||
:audio-duration-ms duration
|
||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})}
|
||||
(when message-id
|
||||
{:response-to message-id})))))))
|
||||
(messages.transport/send-chat-messages
|
||||
[(merge
|
||||
{:chat-id current-chat-id
|
||||
:content-type constants/content-type-audio
|
||||
:audio-path audio-path
|
||||
:audio-duration-ms duration
|
||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})}
|
||||
(when message-id
|
||||
{:response-to message-id}))])))))
|
||||
|
||||
(rf/defn send-sticker-message
|
||||
[cofx {:keys [hash packID pack]} current-chat-id]
|
||||
(when-not (or (string/blank? hash) (and (string/blank? packID) (string/blank? pack)))
|
||||
(chat.message/send-message cofx
|
||||
{:chat-id current-chat-id
|
||||
:content-type constants/content-type-sticker
|
||||
:sticker {:hash hash
|
||||
:pack (int (if (string/blank? packID) pack packID))}
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||
(messages.transport/send-chat-messages
|
||||
cofx
|
||||
[{:chat-id current-chat-id
|
||||
:content-type constants/content-type-sticker
|
||||
:sticker {:hash hash
|
||||
:pack (int (if (string/blank? packID) pack packID))}
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})}])))
|
||||
|
||||
(rf/defn send-edited-message
|
||||
[{:keys [db]
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
{:db (update-in db [:chats chat-id] merge chat)}))
|
||||
|
||||
(rf/defn load-chat
|
||||
{:events [:chats-list/load-chat]}
|
||||
[_ chat-id]
|
||||
{:json-rpc/call [{:method "wakuext_chat"
|
||||
:params [chat-id]
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
[react-native.platform :as platform]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im2.contexts.chat.messages.delete-message.events :as delete-message]
|
||||
[status-im2.contexts.chat.messages.list.events :as message-list]
|
||||
@@ -21,12 +20,6 @@
|
||||
[db chat-id clock-value]
|
||||
(>= (get-in db [:chats chat-id :deleted-at-clock-value]) clock-value))
|
||||
|
||||
(defn add-timeline-message
|
||||
[acc chat-id message-id message]
|
||||
(-> acc
|
||||
(update-in [:db :messages chat-id] assoc message-id message)
|
||||
(update-in [:db :message-lists chat-id] message-list/add message)))
|
||||
|
||||
(defn hide-message
|
||||
"Hide chat message, rebuild message-list"
|
||||
[{:keys [db]} chat-id message-id]
|
||||
@@ -145,14 +138,6 @@
|
||||
:on-error #(log/error "failed to re-send message" %)}]}
|
||||
(update-message-status chat-id message-id :sending)))
|
||||
|
||||
(rf/defn send-message
|
||||
[cofx message]
|
||||
(protocol/send-chat-messages cofx [message]))
|
||||
|
||||
(rf/defn send-messages
|
||||
[cofx messages]
|
||||
(protocol/send-chat-messages cofx messages))
|
||||
|
||||
(rf/defn handle-removed-messages
|
||||
{:events [::handle-removed-messages]}
|
||||
[{:keys [db] :as cofx} removed-messages]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.data-store.reactions :as data-store.reactions]
|
||||
[status-im.transport.message.protocol :as message.protocol]
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
@@ -63,23 +62,6 @@
|
||||
(let [reactions-w-chat-id (map #(assoc % :chat-id chat-id) reactions)]
|
||||
{:db (update db :reactions (process-reactions (:chats db)) reactions-w-chat-id)})))
|
||||
|
||||
|
||||
;; Send reactions
|
||||
|
||||
|
||||
(rf/defn send-emoji-reaction
|
||||
{:events [:models.reactions/send-emoji-reaction]}
|
||||
[{{:keys [current-chat-id]} :db :as cofx} reaction]
|
||||
(message.protocol/send-reaction cofx
|
||||
(update reaction :chat-id #(or % current-chat-id))))
|
||||
|
||||
(rf/defn send-retract-emoji-reaction
|
||||
{:events [:models.reactions/send-emoji-reaction-retraction]}
|
||||
[{{:keys [current-chat-id]} :db :as cofx} reaction]
|
||||
(message.protocol/send-retract-reaction cofx
|
||||
(update reaction :chat-id #(or % current-chat-id))))
|
||||
|
||||
|
||||
(defn message-reactions
|
||||
[current-public-key reactions]
|
||||
(reduce
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
(ns status-im.commands.core
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn handle-prepare-accept-request-address-for-transaction
|
||||
{:events [::prepare-accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message]
|
||||
{:db (assoc db
|
||||
:commands/select-account
|
||||
{:message message
|
||||
:from (wallet.utils/get-default-account (:profile/wallet-accounts
|
||||
db))})
|
||||
:show-select-acc-sheet nil})
|
||||
|
||||
(rf/defn set-selected-account
|
||||
{:events [::set-selected-account]}
|
||||
[{:keys [db]} _ account]
|
||||
{:db (-> (assoc-in db [:commands/select-account :from] account)
|
||||
(assoc :bottom-sheet/show? false))})
|
||||
|
||||
(rf/defn handle-accept-request-address-for-transaction
|
||||
{:events [::accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message-id address]
|
||||
{:db (dissoc db :commands/select-account)
|
||||
:json-rpc/call [{:method "wakuext_acceptRequestAddressForTransaction"
|
||||
:params [message-id address]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(rf/defn handle-decline-request-address-for-transaction
|
||||
{:events [::decline-request-address-for-transaction]}
|
||||
[_ message-id]
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestAddressForTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(rf/defn handle-decline-request-transaction
|
||||
{:events [::decline-request-transaction]}
|
||||
[cofx message-id]
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
@@ -74,6 +74,7 @@
|
||||
:adminSettings :admin-settings
|
||||
:tokenPermissions :token-permissions
|
||||
:communityTokensMetadata :tokens-metadata
|
||||
:introMessage :intro-message
|
||||
:muteTill :muted-till})
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns status-im.contact.chat
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.contexts.contacts.events :as contact]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn contact-code-submitted
|
||||
{:events [:contact.ui/contact-code-submitted]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:contacts/keys [new-identity]} :db :as cofx} new-contact? nickname]
|
||||
(let [{:keys [public-key ens-name]} new-identity]
|
||||
(rf/merge cofx
|
||||
#(if new-contact?
|
||||
(contact/send-contact-request % public-key)
|
||||
{:dispatch [:chat.ui/start-chat public-key ens-name]})
|
||||
#(when new-contact?
|
||||
(navigation/navigate-back %)))))
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns status-im.contact.core
|
||||
(:require
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn open-contact-toggle-list
|
||||
{:events [:contact.ui/start-group-chat-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:group/selected-contacts #{}
|
||||
:new-chat-name "")}
|
||||
(navigation/navigate-to :contact-toggle-list nil)))
|
||||
@@ -85,12 +85,3 @@
|
||||
(assoc acc public-key (enrich-contact contact profile-pictures-visibility own-public-key)))
|
||||
{}
|
||||
contacts))
|
||||
|
||||
(defn get-blocked-contacts
|
||||
[contacts]
|
||||
(reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(if (:blocked? contact)
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
contacts))
|
||||
|
||||
+19
-14
@@ -91,11 +91,11 @@
|
||||
{:chainId :chain-id
|
||||
:removed :removed?})
|
||||
name-details)]
|
||||
{:db (reduce (fn [db {:keys [username removed?] :as name-detail}]
|
||||
{:db (reduce (fn [db {:keys [username removed? chain-id] :as name-detail}]
|
||||
(if removed?
|
||||
(update-in db [:ens/names] dissoc username)
|
||||
(let [old (get-in db [:ens/names username])]
|
||||
(assoc-in db [:ens/names username] (merge old name-detail)))))
|
||||
(update-in db [:ens/names chain-id] dissoc username)
|
||||
(let [old (get-in db [:ens/names chain-id username])]
|
||||
(assoc-in db [:ens/names chain-id username] (merge old name-detail)))))
|
||||
db
|
||||
name-details)}))
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
{:events [:ens/save-username]}
|
||||
[{:keys [db] :as cofx} custom-domain? username redirect-to-summary? connected?]
|
||||
(let [name (fullname custom-domain? username)
|
||||
names (get-in db [:ens/names] [])
|
||||
chain-id (chain/chain-id db)]
|
||||
chain-id (chain/chain-id db)
|
||||
names (get-in db [:ens/names chain-id] [])]
|
||||
(rf/merge cofx
|
||||
(cond-> {:dispatch-n [[:ens/update-usernames [{:username name :chain-id chain-id}]]]}
|
||||
connected? (assoc :json-rpc/call
|
||||
@@ -240,7 +240,8 @@
|
||||
{:events [::set-username-candidate]}
|
||||
[{:keys [db]} username]
|
||||
(let [{:keys [custom-domain?]} (:ens/registration db)
|
||||
usernames (into #{} (keys (get-in db [:ens/names])))
|
||||
chain-id (chain/chain-id db)
|
||||
usernames (into #{} (keys (get-in db [:ens/names chain-id])))
|
||||
state (state custom-domain? username usernames)]
|
||||
(reset! resolve-last-id (random/id))
|
||||
(merge
|
||||
@@ -310,20 +311,23 @@
|
||||
(rf/defn store-name-address
|
||||
{:events [::address-resolved]}
|
||||
[{:keys [db]} username address]
|
||||
{:db (assoc-in db [:ens/names username :address] address)})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (assoc-in db [:ens/names chain-id username :address] address)}))
|
||||
|
||||
(rf/defn store-name-public-key
|
||||
{:events [::public-key-resolved]}
|
||||
[{:keys [db]} username public-key]
|
||||
{:db (assoc-in db [:ens/names username :public-key] public-key)})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (assoc-in db [:ens/names chain-id username :public-key] public-key)}))
|
||||
|
||||
(rf/defn store-expiration-date
|
||||
{:events [::get-expiration-time-success]}
|
||||
[{:keys [now db]} username timestamp]
|
||||
{:db (-> db
|
||||
(assoc-in [:ens/names username :expiration-date]
|
||||
(datetime/timestamp->year-month-day-date timestamp))
|
||||
(assoc-in [:ens/names username :releasable?] (<= timestamp now)))})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (-> db
|
||||
(assoc-in [:ens/names chain-id username :expiration-date]
|
||||
(datetime/timestamp->year-month-day-date timestamp))
|
||||
(assoc-in [:ens/names chain-id username :releasable?] (<= timestamp now)))}))
|
||||
|
||||
(rf/defn navigate-to-name
|
||||
{:events [::navigate-to-name]}
|
||||
@@ -352,7 +356,8 @@
|
||||
(rf/defn remove-username
|
||||
{:events [::remove-username]}
|
||||
[{:keys [db] :as cofx} name]
|
||||
(let [names (get-in db [:ens/names] [])
|
||||
(let [chain-id (chain/chain-id db)
|
||||
names (get-in db [:ens/names chain-id] [])
|
||||
preferred-name (get-in db [:profile/profile :preferred-name])
|
||||
new-names (remove #(= name %) (keys names))
|
||||
{:keys [chain-id username]} (get-in names [name])]
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
status-im.chat.models.input
|
||||
status-im.chat.models.loading
|
||||
status-im.contact.block
|
||||
status-im.contact.chat
|
||||
status-im.contact.core
|
||||
status-im.currency.core
|
||||
status-im.ethereum.subscriptions
|
||||
status-im.fleet.core
|
||||
@@ -32,9 +30,7 @@
|
||||
status-im.pairing.core
|
||||
status-im.profile.core
|
||||
status-im.search.core
|
||||
status-im.signals.core
|
||||
status-im.stickers.core
|
||||
status-im.transport.core
|
||||
status-im.ui.components.invite.events
|
||||
[status-im.ui.components.react :as react]
|
||||
status-im.ui.screens.notifications-settings.events
|
||||
@@ -45,12 +41,12 @@
|
||||
status-im.visibility-status-popover.core
|
||||
status-im.visibility-status-updates.core
|
||||
status-im.waku.core
|
||||
status-im.wallet-connect.core
|
||||
status-im.wallet.accounts.core
|
||||
status-im.wallet.choose-recipient.core
|
||||
[status-im.wallet.core :as wallet]
|
||||
status-im.wallet.custom-tokens.core
|
||||
[status-im2.common.biometric.events :as biometric]
|
||||
status-im2.common.standard-authentication.events
|
||||
[status-im2.common.theme.core :as theme]
|
||||
[status-im2.common.universal-links :as universal-links]
|
||||
[status-im2.constants :as constants]
|
||||
@@ -136,7 +132,7 @@
|
||||
|
||||
(rf/defn on-return-from-background
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [new-account? (get db :onboarding-2/new-account?)
|
||||
(let [new-account? (get db :onboarding/new-account?)
|
||||
app-in-background-since (get db :app-in-background-since)
|
||||
signed-up? (get-in db [:profile/profile :signed-up?])
|
||||
requires-bio-auth (and
|
||||
@@ -194,9 +190,9 @@
|
||||
(rf/merge cofx
|
||||
(cond
|
||||
(= :chat view-id)
|
||||
{:async-storage-set {:chat-id (get-in cofx [:db :current-chat-id])
|
||||
:key-uid (get-in cofx [:db :profile/profile :key-uid])}
|
||||
:db (assoc db :screens/was-focused-once? true)}
|
||||
{:effects.async-storage/set {:chat-id (get-in cofx [:db :current-chat-id])
|
||||
:key-uid (get-in cofx [:db :profile/profile :key-uid])}
|
||||
:db (assoc db :screens/was-focused-once? true)}
|
||||
|
||||
(not (get db :screens/was-focused-once?))
|
||||
{:db (assoc db :screens/was-focused-once? true)})
|
||||
|
||||
@@ -141,14 +141,14 @@
|
||||
(let [pin (get-in db [:keycard :pin :original])
|
||||
puk-restore? (get-in db [:keycard :pin :puk-restore?])]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:login pin
|
||||
:confirmation []
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pin-changed)}}
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:login pin
|
||||
:confirmation []
|
||||
:error-label nil})
|
||||
:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pin-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
(if puk-restore?
|
||||
(navigation/navigate-to :multiaccounts nil)
|
||||
@@ -160,14 +160,14 @@
|
||||
{:events [:keycard.callback/on-change-puk-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/puk-changed)}}
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:error-label nil})
|
||||
:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/puk-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
@@ -175,13 +175,13 @@
|
||||
{:events [:keycard.callback/on-change-pairing-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:pairing-code nil
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pairing-changed)}}
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:pairing-code nil
|
||||
:error-label nil})
|
||||
:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pairing-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
|
||||
@@ -293,14 +293,14 @@
|
||||
(rf/defn show-wrong-keycard-alert
|
||||
[_]
|
||||
(log/debug "show-wrong-keycard-alert")
|
||||
{:utils/show-popup {:title (i18n/label :t/wrong-card)
|
||||
:content (i18n/label :t/wrong-card-text)}})
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/wrong-card)
|
||||
:content (i18n/label :t/wrong-card-text)}})
|
||||
|
||||
(rf/defn unauthorized-operation
|
||||
[cofx]
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/keycard-unauthorized-operation)}}
|
||||
{:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/keycard-unauthorized-operation)}}
|
||||
(clear-on-card-connected)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
(rf/defn show-keycard-has-multiaccount-alert
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :setup-step] nil)
|
||||
:utils/show-confirmation {:title nil
|
||||
:content (i18n/label
|
||||
:t/keycard-has-multiaccount-on-it)
|
||||
:cancel-button-text ""
|
||||
:confirm-button-text :t/okay}}))
|
||||
{:db (assoc-in db [:keycard :setup-step] nil)
|
||||
:effects.utils/show-confirmation {:title nil
|
||||
:content (i18n/label
|
||||
:t/keycard-has-multiaccount-on-it)
|
||||
:cancel-button-text ""
|
||||
:confirm-button-text :t/okay}}))
|
||||
|
||||
(rf/defn load-pin-screen
|
||||
[{:keys [db] :as cofx}]
|
||||
@@ -548,10 +548,11 @@
|
||||
|
||||
(rf/defn show-no-keycard-applet-alert
|
||||
[_]
|
||||
{:utils/show-confirmation {:title (i18n/label :t/no-keycard-applet-on-card)
|
||||
:content (i18n/label :t/keycard-applet-install-instructions)
|
||||
:cancel-button-text ""
|
||||
:confirm-button-text :t/okay}})
|
||||
{:effects.utils/show-confirmation {:title (i18n/label :t/no-keycard-applet-on-card)
|
||||
:content (i18n/label
|
||||
:t/keycard-applet-install-instructions)
|
||||
:cancel-button-text ""
|
||||
:confirm-button-text :t/okay}})
|
||||
|
||||
;; NOTE: Maybe replaced by multiple events based on on flow to make it easier to maintain.
|
||||
;; Because there are many execution paths it is harder to follow all possible states.
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
(do
|
||||
(log/debug (str "Cannot start keycard installation from state: " card-state))
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
(navigation/navigate-to :keycard-authentication-method nil))))))
|
||||
|
||||
(rf/defn load-preparing-screen
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
@@ -221,12 +220,12 @@
|
||||
(rf/defn on-backup-success
|
||||
[{:keys [db] :as cofx} backup-type]
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-access-reset
|
||||
:t/keycard-backup-success-title))
|
||||
:content (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-can-use-with-new-passcode
|
||||
:t/keycard-backup-success-body))}}
|
||||
{:effects.utils/show-popup {:title (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-access-reset
|
||||
:t/keycard-backup-success-title))
|
||||
:content (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-can-use-with-new-passcode
|
||||
:t/keycard-backup-success-body))}}
|
||||
(cond
|
||||
(multiaccounts.model/logged-in? db)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])
|
||||
@@ -278,7 +277,7 @@
|
||||
{:db (-> db
|
||||
(assoc-in [:profile/profiles-overview key-uid :keycard-pairing] pairing)
|
||||
(assoc :profile/login account)
|
||||
(assoc :auth-method keychain/auth-method-none)
|
||||
(assoc :auth-method "none")
|
||||
(update :keycard dissoc :flow :migration-password)
|
||||
(dissoc :recovered-account?))
|
||||
::finish-migration [account settings password encryption-pass login-params]}))
|
||||
@@ -373,4 +372,3 @@
|
||||
cofx
|
||||
{:on-card-connected :keycard/load-recovering-key-screen
|
||||
:handler (common/dispatch-event :keycard/import-multiaccount)}))
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title ""
|
||||
:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/card-unpaired)}}
|
||||
(common/clear-on-card-connected)
|
||||
(remove-pairing-from-multiaccount nil)
|
||||
@@ -100,7 +100,7 @@
|
||||
:error-label nil
|
||||
:on-verified nil})
|
||||
:keycard/get-application-info nil
|
||||
:utils/show-popup {:title ""
|
||||
:effects.utils/show-popup {:title ""
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
(common/clear-on-card-connected)
|
||||
(navigation/navigate-to :keycard-settings nil)))
|
||||
@@ -139,15 +139,14 @@
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
|
||||
:effects.utils/show-popup {:title (i18n/label (if keys-removed-from-card?
|
||||
:t/profile-deleted-title
|
||||
:t/database-reset-title))
|
||||
:content (i18n/label (if keys-removed-from-card?
|
||||
:t/profile-deleted-keycard
|
||||
:t/database-reset-content))
|
||||
:on-dismiss #(re-frame/dispatch [:logout])}}
|
||||
;;should be reimplemented
|
||||
;;:key-storage/delete-profile {:key-uid key-uid
|
||||
;;should be reimplemented :key-storage/delete-profile {:key-uid key-uid
|
||||
;;:on-success #(log/debug "[keycard] remove account ok")
|
||||
;; :on-error #(log/warn "[keycard] remove account: " %)}
|
||||
(common/clear-on-card-connected)
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
{:events [:mailserver.ui/request-error-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [mailserver-error (:mailserver/request-error db)]
|
||||
{:utils/show-confirmation
|
||||
{:effects.utils/show-confirmation
|
||||
{:title (i18n/label :t/mailserver-request-error-title)
|
||||
:content (i18n/label :t/mailserver-request-error-content
|
||||
{:error mailserver-error})
|
||||
@@ -290,8 +290,7 @@
|
||||
[{:method "mailservers_addMailserver"
|
||||
:params [(mailserver->rpc mailserver current-fleet)]
|
||||
:on-success (fn []
|
||||
;; we naively logout if the user is connected to
|
||||
;; the edited mailserver
|
||||
;; we naively logout if the user is connected to the edited mailserver
|
||||
(when current
|
||||
(re-frame/dispatch
|
||||
[:multiaccounts.logout.ui/logout-confirmed]))
|
||||
@@ -413,3 +412,17 @@
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :mailserver.edit/mailserver)}
|
||||
(navigation/navigate-to :edit-mailserver nil)))
|
||||
|
||||
(defn add-mailservers
|
||||
[db mailservers]
|
||||
(reduce (fn [db {:keys [fleet id name] :as mailserver}]
|
||||
(let [updated-mailserver
|
||||
(-> mailserver
|
||||
(update :id keyword)
|
||||
(assoc :name (if (seq name) name id))
|
||||
(dissoc :fleet))]
|
||||
(assoc-in db
|
||||
[:mailserver/mailservers (keyword fleet) (keyword id)]
|
||||
updated-mailserver)))
|
||||
db
|
||||
mailservers))
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
(rf/merge cofx
|
||||
{:set-root :progress
|
||||
:chat.ui/clear-inputs nil
|
||||
:shell/reset-state nil
|
||||
:effects.shell/reset-state nil
|
||||
:hide-popover nil
|
||||
::logout nil
|
||||
:profile.settings/webview-debug-changed false
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
(rf/defn connect-failure
|
||||
{:events [::connect-failure]}
|
||||
[_ reason]
|
||||
{:utils/show-popup
|
||||
{:effects.utils/show-popup
|
||||
{:title (i18n/label :t/error)
|
||||
:content (str reason)}})
|
||||
|
||||
|
||||
@@ -165,9 +165,9 @@
|
||||
(if (< (count (filter :enabled? (vals (get-in cofx [:db :pairing/installations]))))
|
||||
(inc config/max-installations))
|
||||
{:pairing/enable-installation [installation-id]}
|
||||
{:utils/show-popup {:title (i18n/label :t/pairing-maximum-number-reached-title)
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/pairing-maximum-number-reached-title)
|
||||
|
||||
:content (i18n/label :t/pairing-maximum-number-reached-content)}}))
|
||||
:content (i18n/label :t/pairing-maximum-number-reached-content)}}))
|
||||
|
||||
(rf/defn disable-fx
|
||||
{:events [:pairing.ui/disable-installation-pressed]}
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
[{:keys [db] :as cofx} {:keys [chat-id]}]
|
||||
(if-not (own-public-key? db chat-id)
|
||||
{:dispatch [:chat.ui/start-chat chat-id]}
|
||||
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/can-not-add-yourself)}}))
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/can-not-add-yourself)}}))
|
||||
|
||||
(rf/defn handle-group-chat
|
||||
[cofx params]
|
||||
@@ -71,9 +71,9 @@
|
||||
(navigation/navigate-back))
|
||||
|
||||
:else
|
||||
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/ens-name-not-found)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/ens-name-not-found)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
|
||||
|
||||
(rf/defn handle-eip681
|
||||
[cofx data]
|
||||
@@ -103,9 +103,9 @@
|
||||
(log/info "Unable to find matcher for scanned value"
|
||||
{:type type
|
||||
:event ::match-scanned-value})
|
||||
{:dispatch [:navigate-back]
|
||||
:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
|
||||
{:dispatch [:navigate-back]
|
||||
:effects.utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
|
||||
|
||||
(rf/defn on-scan
|
||||
{:events [::on-scan-success]}
|
||||
|
||||
@@ -78,9 +78,9 @@
|
||||
[{:keys [db]} data typed? result]
|
||||
(let [{:keys [result error]} (types/json->clj result)]
|
||||
(if error
|
||||
{:dispatch [:signing.ui/cancel-is-pressed]
|
||||
:utils/show-popup {:title (i18n/label :t/sign-request-failed)
|
||||
:content (:message error)}}
|
||||
{:dispatch [:signing.ui/cancel-is-pressed]
|
||||
:effects.utils/show-popup {:title (i18n/label :t/sign-request-failed)
|
||||
:content (:message error)}}
|
||||
{:db (update db
|
||||
:keycard assoc
|
||||
:hash result
|
||||
|
||||
@@ -60,10 +60,17 @@
|
||||
{:state state
|
||||
:username username}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens/current-names
|
||||
:<- [:ens/names]
|
||||
:<- [:chain-id]
|
||||
(fn [[all-names chain-id]]
|
||||
(get all-names chain-id)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens.name/screen
|
||||
:<- [:get-screen-params :ens-name-details]
|
||||
:<- [:ens/names]
|
||||
:<- [:ens/current-names]
|
||||
(fn [[name ens]]
|
||||
(let [{:keys [address public-key expiration-date releasable?]} (get ens name)
|
||||
pending? (nil? address)]
|
||||
@@ -79,7 +86,7 @@
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens.main/screen
|
||||
:<- [:ens/names]
|
||||
:<- [:ens/current-names]
|
||||
:<- [:profile/profile]
|
||||
:<- [:ens/preferred-name]
|
||||
:<- [:ens/registrations]
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
(ns ^{:doc "API to init and stop whisper messaging"} status-im.transport.core
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.pairing.core :as pairing]
|
||||
[status-im.stickers.core :as stickers]
|
||||
status-im.transport.shh
|
||||
[status-im2.common.universal-links :as universal-links]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn set-node-info
|
||||
{:events [:transport.callback/node-info-fetched]}
|
||||
[{:keys [db]} node-info]
|
||||
{:db (assoc db :node-info node-info)})
|
||||
|
||||
(rf/defn fetch-node-info-fx
|
||||
[_]
|
||||
{:json-rpc/call [{:method "admin_nodeInfo"
|
||||
:on-success #(re-frame/dispatch [:transport.callback/node-info-fetched %])
|
||||
:on-error #(log/error "node-info: failed error" %)}]})
|
||||
|
||||
(defn add-mailservers
|
||||
[db mailservers]
|
||||
(reduce (fn [db {:keys [fleet id name] :as mailserver}]
|
||||
(let [updated-mailserver
|
||||
(-> mailserver
|
||||
(update :id keyword)
|
||||
(assoc :name (if (seq name) name id))
|
||||
(dissoc :fleet))]
|
||||
(assoc-in db
|
||||
[:mailserver/mailservers (keyword fleet) (keyword id)]
|
||||
updated-mailserver)))
|
||||
db
|
||||
mailservers))
|
||||
|
||||
(rf/defn start-messenger
|
||||
"We should only start receiving messages/processing topics once all the
|
||||
initializiation is completed, otherwise we might receive messages/topics
|
||||
when the state has not been properly initialized."
|
||||
[_]
|
||||
{:json-rpc/call [{:method "wakuext_startMessenger"
|
||||
:on-success #(re-frame/dispatch [::messenger-started %])
|
||||
:on-error #(log/error "failed to start messenger")}]})
|
||||
|
||||
(rf/defn messenger-started
|
||||
{:events [::messenger-started]}
|
||||
[{:keys [db] :as cofx} {:keys [mailservers] :as response}]
|
||||
(log/info "Messenger started")
|
||||
(let [new-account? (get db :onboarding-2/new-account?)]
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :messenger/started? true)
|
||||
(add-mailservers mailservers))}
|
||||
(fetch-node-info-fx)
|
||||
(pairing/init)
|
||||
(stickers/load-packs)
|
||||
(when-not new-account?
|
||||
(universal-links/process-stored-event)))))
|
||||
@@ -1,59 +0,0 @@
|
||||
(ns ^{:doc "Protocol API and protocol utils"} status-im.transport.message.protocol
|
||||
(:require
|
||||
[clojure.set :as set]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- link-preview->rpc
|
||||
[preview]
|
||||
(update preview
|
||||
:thumbnail
|
||||
(fn [thumbnail]
|
||||
(set/rename-keys thumbnail {:data-uri :dataUri}))))
|
||||
|
||||
(defn build-message
|
||||
[msg]
|
||||
(-> msg
|
||||
(update :link-previews #(map link-preview->rpc %))
|
||||
(set/rename-keys
|
||||
{:album-id :albumId
|
||||
:audio-duration-ms :audioDurationMs
|
||||
:audio-path :audioPath
|
||||
:chat-id :chatId
|
||||
:community-id :communityId
|
||||
:content-type :contentType
|
||||
:ens-name :ensName
|
||||
:image-height :imageHeight
|
||||
:image-path :imagePath
|
||||
:image-width :imageWidth
|
||||
:link-previews :linkPreviews
|
||||
:response-to :responseTo
|
||||
:sticker :sticker
|
||||
:text :text})))
|
||||
|
||||
(rf/defn send-chat-messages
|
||||
[_ messages]
|
||||
{:json-rpc/call [{:method "wakuext_sendChatMessages"
|
||||
:params [(mapv build-message messages)]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])
|
||||
:on-error #(do
|
||||
(log/warn "failed to send a message" %)
|
||||
(js/alert (str "failed to send a message: " %)))}]})
|
||||
|
||||
(rf/defn send-reaction
|
||||
[_ {:keys [message-id chat-id emoji-id]}]
|
||||
{:json-rpc/call [{:method "wakuext_sendEmojiReaction"
|
||||
:params [chat-id message-id emoji-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to send a reaction" %)}]})
|
||||
|
||||
(rf/defn send-retract-reaction
|
||||
[_ {:keys [emoji-reaction-id]}]
|
||||
{:json-rpc/call [{:method "wakuext_sendEmojiReactionRetraction"
|
||||
:params [emoji-reaction-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to send a reaction retraction" %)}]})
|
||||
@@ -1,35 +0,0 @@
|
||||
(ns ^{:doc "Whisper API and events for managing keys and posting messages"} status-im.transport.shh
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn generate-sym-key-from-password
|
||||
[{:keys [password on-success on-error]}]
|
||||
(json-rpc/call {:method "waku_generateSymKeyFromPassword"
|
||||
:params [password]
|
||||
:on-success on-success
|
||||
:on-error on-error}))
|
||||
|
||||
(defn get-sym-key
|
||||
[{:keys [sym-key-id on-success on-error]}]
|
||||
(json-rpc/call {:method "waku_getSymKey"
|
||||
:params [sym-key-id]
|
||||
:on-success on-success
|
||||
:on-error on-error}))
|
||||
|
||||
(defn log-error
|
||||
[error]
|
||||
(log/error :shh/get-new-sym-key-error error))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/generate-sym-key-from-password
|
||||
(fn [{:keys [password on-success]}]
|
||||
(generate-sym-key-from-password
|
||||
{:password password
|
||||
:on-success (fn [sym-key-id]
|
||||
(get-sym-key {:sym-key-id sym-key-id
|
||||
:on-success (fn [sym-key]
|
||||
(on-success sym-key sym-key-id))
|
||||
:on-error log-error}))
|
||||
:on-error log-error})))
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns ^{:doc "Utils for transport layer"} status-im.transport.utils
|
||||
(:require
|
||||
[clojure.string :as string]))
|
||||
|
||||
(defn extract-enode-id
|
||||
[enode]
|
||||
(-> enode
|
||||
(string/split #"/")
|
||||
(get 2 "")
|
||||
(string/split #":")
|
||||
(get 0 "")
|
||||
(string/split "@")
|
||||
(get 0)))
|
||||
|
||||
(defn extract-url-components
|
||||
[address]
|
||||
(when address
|
||||
(rest (re-matches #"enode://(.*?)@(.*):(.*)" address))))
|
||||
@@ -7,6 +7,11 @@
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(re-frame/dispatch event))
|
||||
|
||||
(defn- normal-mode-settings-data
|
||||
[{:keys [network-name
|
||||
current-log-level
|
||||
@@ -103,7 +108,13 @@
|
||||
#(re-frame/dispatch
|
||||
[:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)])
|
||||
:accessory :switch
|
||||
:active waku-bloom-filter-mode}]))
|
||||
:active waku-bloom-filter-mode}
|
||||
{:size :small
|
||||
:title (i18n/label :t/set-currency)
|
||||
:accessibility-label :wallet-change-currency
|
||||
:on-press #(hide-sheet-and-dispatch
|
||||
[:navigate-to :currency-settings])
|
||||
:chevron true}]))
|
||||
|
||||
(defn- flat-list-data
|
||||
[options]
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
{:events [::on-delete-profile-success]}
|
||||
[cofx]
|
||||
(log/info "[delete-profile] on-success")
|
||||
{:utils/show-popup
|
||||
{:effects.utils/show-popup
|
||||
{:title (i18n/label :t/profile-deleted-title)
|
||||
:content (i18n/label :t/profile-deleted-content)
|
||||
:on-dismiss #(re-frame/dispatch [:logout])}})
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
:key :your-data-belongs-to-you-description}]
|
||||
[react/view {:style styles/intro-button}
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])}
|
||||
{:on-press #(do (re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])
|
||||
(re-frame/dispatch [:profile.settings/mnemonic-was-shown]))}
|
||||
(i18n/label :t/ok-continue)]]])
|
||||
|
||||
(defn six-words
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
key-uid]
|
||||
:as profile}
|
||||
@(re-frame/subscribe [:profile/profile-with-image])
|
||||
customization-color (or (:color @(re-frame/subscribe [:onboarding-2/profile]))
|
||||
customization-color (or (:color @(re-frame/subscribe [:onboarding/profile]))
|
||||
@(re-frame/subscribe [:profile/customization-color key-uid]))
|
||||
on-share #(re-frame/dispatch [:show-popover
|
||||
{:view :share-chat-key
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
(ns status-im.ui.screens.wallet.send.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs] :as views])
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.commands.core :as commands]
|
||||
[status-im.ui.components.bottom-panel.views :as bottom-panel]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.core :as components.core]
|
||||
@@ -129,47 +127,6 @@
|
||||
" "
|
||||
(:code wallet-currency))])))
|
||||
|
||||
(defn select-account-sheet
|
||||
[{:keys [from message]}]
|
||||
[react/view {:style (styles/acc-sheet)}
|
||||
[header
|
||||
{:small-screen? false
|
||||
:label :t/select-account}]
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 24
|
||||
:align-items :center
|
||||
:margin-vertical 16}]
|
||||
[components.core/list-header
|
||||
(i18n/label :t/from-capitalized)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from nil ::commands/set-selected-account]]]
|
||||
[toolbar/toolbar
|
||||
{:left
|
||||
[react/view {:padding-horizontal 8}
|
||||
[components.core/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:set :commands/select-account nil])}
|
||||
(i18n/label :t/cancel)]]
|
||||
:right
|
||||
[components.core/button
|
||||
{:accessibility-label :select-account-bottom-sheet
|
||||
:disabled (nil? from)
|
||||
:on-press #(re-frame/dispatch
|
||||
[::commands/accept-request-address-for-transaction
|
||||
(:message-id message)
|
||||
(:address from)])}
|
||||
(i18n/label :t/share)]}]])
|
||||
|
||||
(defview select-account
|
||||
[]
|
||||
(letsubs [data [:commands/select-account]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
data
|
||||
select-account-sheet
|
||||
#(re-frame/dispatch [:hide-select-acc-sheet])]))
|
||||
|
||||
(views/defview request-transaction
|
||||
[_]
|
||||
(views/letsubs [{:keys [amount-error amount-text from token sign-enabled?] :as tx}
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def auth-method-biometric "biometric")
|
||||
(def auth-method-biometric-prepare "biometric-prepare")
|
||||
(def auth-method-none "none")
|
||||
|
||||
(defn- whisper-key-name
|
||||
[address]
|
||||
(str address "-whisper"))
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[react-native.mail :as react-native-mail]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.build :as build]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
@@ -38,6 +37,11 @@
|
||||
{:json-rpc/call [{:method "web3_clientVersion"
|
||||
:on-success #(re-frame/dispatch [:logging/store-web3-client-version %])}]})
|
||||
|
||||
(defn extract-url-components
|
||||
[address]
|
||||
(when address
|
||||
(rest (re-matches #"enode://(.*?)@(.*):(.*)" address))))
|
||||
|
||||
(defn email-body
|
||||
"logs attached"
|
||||
[{:keys [:web3-node-version :mailserver/current-id
|
||||
@@ -46,7 +50,7 @@
|
||||
build-version (str build/version " (" build-number ")")
|
||||
separator (string/join (take 40 (repeat "-")))
|
||||
[enode-id ip-address port]
|
||||
(transport.utils/extract-url-components (:enode node-info))]
|
||||
(extract-url-components (:enode node-info))]
|
||||
(string/join
|
||||
"\n"
|
||||
(concat [(i18n/label :t/report-bug-email-template
|
||||
@@ -68,7 +72,7 @@
|
||||
(mapcat
|
||||
(fn [{:keys [enode]}]
|
||||
(let [[enode-id ip-address port]
|
||||
(transport.utils/extract-url-components enode)]
|
||||
(extract-url-components enode)]
|
||||
[(str "id: " enode-id)
|
||||
(str "ip: " ip-address)
|
||||
(str "port: " port)
|
||||
@@ -151,15 +155,15 @@
|
||||
(rf/defn show-client-error
|
||||
{:events [:show-client-error]}
|
||||
[_]
|
||||
{:utils/show-popup {:title (i18n/label :t/cant-report-bug)
|
||||
:content (i18n/label :t/mail-should-be-configured)}})
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/cant-report-bug)
|
||||
:content (i18n/label :t/mail-should-be-configured)}})
|
||||
|
||||
(rf/defn show-logs-dialog
|
||||
{:events [:shake-event]}
|
||||
[{:keys [db]}]
|
||||
(when-not (:logging/dialog-shown? db)
|
||||
{:db (assoc db :logging/dialog-shown? true)
|
||||
:utils/show-confirmation
|
||||
:effects.utils/show-confirmation
|
||||
(cond-> {:title (i18n/label :t/send-logs)
|
||||
:content (i18n/label :t/send-logs-to
|
||||
{:email report-email})
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns ^{:doc "Pairing utils"} status-im.utils.pairing)
|
||||
|
||||
(defn has-paired-installations?
|
||||
[cofx]
|
||||
(let [our-installation-id (get-in cofx [:db :profile/profile :installation-id])]
|
||||
(->>
|
||||
(get-in cofx [:db :pairing/installations])
|
||||
vals
|
||||
(some (fn [{:keys [enabled? installation-id]}]
|
||||
(and (not= installation-id our-installation-id)
|
||||
enabled?))))))
|
||||
@@ -1,120 +0,0 @@
|
||||
(ns status-im.utils.snoopy
|
||||
(:require
|
||||
["react-native/Libraries/vendor/emitter/EventEmitter" :refer [EventEmitter]]
|
||||
["rn-snoopy" :default snoopy]
|
||||
["rn-snoopy/stream/bars" :default bars]
|
||||
["rn-snoopy/stream/buffer" :default buffer]
|
||||
["rn-snoopy/stream/filter" :default sn-filter]
|
||||
[clojure.string :as string]
|
||||
[status-im2.config :as config]))
|
||||
|
||||
(defn create-filter
|
||||
[f]
|
||||
(fn [^js message]
|
||||
(let [method (.-method message)
|
||||
module (.-module message)
|
||||
^js args (.-args message)
|
||||
first-arg (when (pos? (.-length args))
|
||||
(aget args 0))]
|
||||
(f {:method method
|
||||
:module module
|
||||
:first-arg first-arg}))))
|
||||
|
||||
(defn status-module-filter
|
||||
[{:keys [method module first-arg]}]
|
||||
(or (= module "Status")
|
||||
(and (= module "RCTNativeAppEventEmitter")
|
||||
(= method "emit")
|
||||
(= first-arg "gethEvent"))
|
||||
(and
|
||||
(string? method)
|
||||
(string/starts-with? method "<callback for Status."))))
|
||||
|
||||
(defn timer-filter
|
||||
[{:keys [method]}]
|
||||
(contains? #{"callTimers" "createTimer"} method))
|
||||
|
||||
(defn websocket-filter
|
||||
[{:keys [module first-arg]}]
|
||||
(or (= module "WebSocketModule")
|
||||
(and (= module "RCTDeviceEventEmitter")
|
||||
(contains? #{"websocketFailed" "websocketMessage"} first-arg))))
|
||||
|
||||
(defn ui-manager-filter
|
||||
[{:keys [module]}]
|
||||
(= module "UIManager"))
|
||||
|
||||
(defn touches-filter
|
||||
[{:keys [method module]}]
|
||||
(and (= module "RCTEventEmitter")
|
||||
(= method "receiveTouches")))
|
||||
|
||||
(defn native-animation-filter
|
||||
[{:keys [method module]}]
|
||||
(or (= module "NativeAnimatedModule")
|
||||
(and
|
||||
(string? method)
|
||||
(string/starts-with? method "<callback for NativeAnimatedModule."))))
|
||||
|
||||
(defn keyboard-observer-filter
|
||||
[{:keys [module]}]
|
||||
;; mostly all calls to KeyboardObserver are done by FlatList
|
||||
(= module "KeyboardObserver"))
|
||||
|
||||
(defn threshold-warnings
|
||||
[{:keys [filter-fn label tick? print-events? threshold events threshold-message]}]
|
||||
(.subscribe ^js
|
||||
((bars
|
||||
(fn [^js a] (.-length a))
|
||||
threshold
|
||||
tick?
|
||||
true
|
||||
label
|
||||
threshold-message)
|
||||
((buffer)
|
||||
((sn-filter (create-filter filter-fn)
|
||||
print-events?)
|
||||
events)))))
|
||||
|
||||
;; In order to enable snoopy set SNOOPY=1 in .env file.
|
||||
;; By default events are not printed and you will see warnings only when
|
||||
;; the number of events is exceeding the threshold.
|
||||
;; For debugging UI perf, in particular the number of bridge calls caused
|
||||
;; by view components set `:print-events?=true` for `ui-manager-filter`,
|
||||
;; and then collect printed data in logs.
|
||||
(defn subscribe!
|
||||
[]
|
||||
(when config/snoopy-enabled?
|
||||
(let [emitter-class EventEmitter
|
||||
emitter (emitter-class.)
|
||||
events (.stream snoopy emitter)]
|
||||
(threshold-warnings
|
||||
{:filter-fn (constantly true)
|
||||
:label "all messages"
|
||||
:threshold-message "too many calls to bridge, something suspicious is happening"
|
||||
:tick? false
|
||||
:print-events? false
|
||||
:threshold 400
|
||||
:events events})
|
||||
|
||||
(threshold-warnings
|
||||
{:filter-fn timer-filter
|
||||
:label "timer"
|
||||
:threshold-message "too many setTimeout/setInterval calls"
|
||||
:tick? false
|
||||
:print-events? false
|
||||
:threshold 70
|
||||
:events events})
|
||||
|
||||
(threshold-warnings
|
||||
{:filter-fn ui-manager-filter
|
||||
:label "timer"
|
||||
:threshold-message (str
|
||||
"too many calls to UIManager, most likely during navigation. "
|
||||
"Please consider preloading of screens or lazy loading of some components")
|
||||
:tick? false
|
||||
:print-events? true
|
||||
;; todo(rasom): revisit this number when/if
|
||||
;; https://github.com/status-im/status-mobile/pull/2849 will be merged
|
||||
:threshold 200
|
||||
:events events}))))
|
||||
@@ -1,31 +0,0 @@
|
||||
(ns status-im.utils.wallet-connect
|
||||
(:require
|
||||
["@react-native-async-storage/async-storage" :default AsyncStorage]
|
||||
["@walletconnect/client" :refer [CLIENT_EVENTS] :default WalletConnectClient]
|
||||
[clojure.string :as string]
|
||||
[status-im2.config :as config]))
|
||||
|
||||
(defn init
|
||||
[on-success on-error]
|
||||
(-> ^js WalletConnectClient
|
||||
(.init (clj->js {:controller true
|
||||
:projectId config/wallet-connect-project-id
|
||||
:logger "debug"
|
||||
:metadata config/default-wallet-connect-metadata
|
||||
:storageOptions {:asyncStorage ^js AsyncStorage}}))
|
||||
(.then on-success)
|
||||
(.catch on-error)))
|
||||
|
||||
(defn session-request-event [] (.-request (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-created-event [] (.-created (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-deleted-event [] (.-deleted (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-proposal-event [] (.-proposal (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-updated-event [] (.-updated (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn url?
|
||||
[url]
|
||||
(string/starts-with? url "wc:"))
|
||||
@@ -359,8 +359,8 @@
|
||||
(let [deleted-address (:address account)
|
||||
dapps-address (get-in cofx [:db :profile/profile :dapps-address])]
|
||||
(if (= (string/lower-case dapps-address) (string/lower-case deleted-address))
|
||||
{:utils/show-popup {:title (i18n/label :t/warning)
|
||||
:content (i18n/label :t/account-is-used)}}
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/warning)
|
||||
:content (i18n/label :t/account-is-used)}}
|
||||
{:key-storage/delete-imported-key
|
||||
{:key-uid (get-in db [:profile/profile :key-uid])
|
||||
:address (:address account)
|
||||
@@ -379,8 +379,8 @@
|
||||
(assoc-in [:add-account :scanned-address] address)
|
||||
(assoc-in [:add-account :address] address))}
|
||||
(when-not address
|
||||
{:utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/invalid-address-qr-code)}}))
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/invalid-address-qr-code)}}))
|
||||
(navigation/navigate-back))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
@@ -392,4 +392,3 @@
|
||||
{:events [:wallet-legacy.accounts/share]}
|
||||
[_ address]
|
||||
{:list.selection/open-share {:message (eip55/address->checksum address)}})
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.qr-scanner.core :as qr-scaner]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im2.common.router :as router]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
@@ -173,11 +172,7 @@
|
||||
(if (links/universal-link? uri)
|
||||
{:dispatch [:universal-links/handle-url uri]}
|
||||
{:browser/show-browser-selection uri})
|
||||
(if (wallet-connect/url? uri)
|
||||
{:ui/show-error "Wallet Connect not implemented"}
|
||||
;; Re-enable with https://github.com/status-im/status-mobile/issues/13429
|
||||
;; {:dispatch [::qr-scaner/handle-wallet-connect-uri {:data uri}]}
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})}))))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})))
|
||||
|
||||
(rf/defn qr-scanner-result
|
||||
{:events [:wallet-legacy.send/qr-scanner-result]}
|
||||
|
||||
@@ -246,8 +246,8 @@
|
||||
assets (get visible-tokens chain)
|
||||
tokens (->> (vals all-tokens)
|
||||
(remove #(or (:hidden? %)
|
||||
;;if not scan-all-tokens? remove not
|
||||
;;visible tokens
|
||||
;;if not scan-all-tokens? remove
|
||||
;;not visible tokens
|
||||
(and (not scan-all-tokens?)
|
||||
(not (get assets (:symbol %))))))
|
||||
(reduce (fn [acc {:keys [address symbol]}]
|
||||
@@ -822,8 +822,8 @@
|
||||
(rf/defn get-buy-crypto-preference
|
||||
{:events [::get-buy-crypto]}
|
||||
[_]
|
||||
{:async-storage-get {:keys [:buy-crypto-hidden]
|
||||
:cb #(re-frame/dispatch [::store-buy-crypto-preference %])}})
|
||||
{:effects.async-storage/get {:keys [:buy-crypto-hidden]
|
||||
:cb #(re-frame/dispatch [::store-buy-crypto-preference %])}})
|
||||
|
||||
(rf/defn wallet-will-focus
|
||||
{:events [::wallet-stack]}
|
||||
@@ -844,8 +844,8 @@
|
||||
(rf/defn hide-buy-crypto
|
||||
{:events [::hide-buy-crypto]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :wallet-legacy/buy-crypto-hidden true)
|
||||
:async-storage-set {:buy-crypto-hidden true}})
|
||||
{:db (assoc db :wallet-legacy/buy-crypto-hidden true)
|
||||
:effects.async-storage/set {:buy-crypto-hidden true}})
|
||||
|
||||
(rf/defn store-buy-crypto
|
||||
{:events [::store-buy-crypto-preference]}
|
||||
@@ -1023,8 +1023,8 @@
|
||||
(rf/defn switch-transactions-management-enabled
|
||||
{:events [:multiaccounts.ui/switch-transactions-management-enabled]}
|
||||
[{:keys [db]} enabled?]
|
||||
{:async-storage-set {:transactions-management-enabled? enabled?}
|
||||
:db (assoc db :wallet-legacy/transactions-management-enabled? enabled?)})
|
||||
{:effects.async-storage/set {:transactions-management-enabled? enabled?}
|
||||
:db (assoc db :wallet-legacy/transactions-management-enabled? enabled?)})
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet-legacy/initialize-transactions-management-enabled
|
||||
@@ -1072,10 +1072,9 @@
|
||||
true])}))
|
||||
2000)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
;;TODO: this could be replaced by a single API call on status-go side
|
||||
:wallet-legacy/initialize-wallet
|
||||
(fn [[network-id network callback]]
|
||||
;;TODO: this could be replaced by a single API call on status-go side
|
||||
(re-frame/reg-fx :wallet-legacy/initialize-wallet
|
||||
(fn [[network-id _network callback]]
|
||||
(-> (js/Promise.all
|
||||
(clj->js
|
||||
[(js/Promise.
|
||||
@@ -1083,24 +1082,6 @@
|
||||
(json-rpc/call {:method "accounts_getAccounts"
|
||||
:on-success resolve-fn
|
||||
:on-error reject})))
|
||||
(js/Promise.
|
||||
(fn [resolve-fn _]
|
||||
(json-rpc/call
|
||||
{:method "wallet_addEthereumChain"
|
||||
:params
|
||||
[{:isTest false
|
||||
:tokenOverrides []
|
||||
:rpcUrl (get-in network [:config :UpstreamConfig :URL])
|
||||
:chainColor "green"
|
||||
:chainName (:name network)
|
||||
:nativeCurrencyDecimals 10
|
||||
:shortName "erc20"
|
||||
:layer 1
|
||||
:chainId (int network-id)
|
||||
:enabled false
|
||||
:fallbackURL (get-in network [:config :UpstreamConfig :URL])}]
|
||||
:on-success resolve-fn
|
||||
:on-error (fn [_] (resolve-fn nil))})))
|
||||
(js/Promise.
|
||||
(fn [resolve-fn _]
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
(rf/defn not-supported
|
||||
{:events [:wallet-legacy.custom-token/not-supported]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet-legacy/custom-token-screen :in-progress?] nil)
|
||||
:utils/show-popup {:content (i18n/label :t/contract-isnt-supported)}})
|
||||
{:db (assoc-in db [:wallet-legacy/custom-token-screen :in-progress?] nil)
|
||||
:effects.utils/show-popup {:content (i18n/label :t/contract-isnt-supported)}})
|
||||
|
||||
(rf/defn add-custom-token
|
||||
{:events [:wallet-legacy.custom-token.ui/add-pressed]}
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
(ns status-im.wallet-connect.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn proposal-handler
|
||||
{:events [:wallet-connect/proposal]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [proposal (types/js->clj request-event)
|
||||
proposer (:proposer proposal)
|
||||
metadata (:metadata proposer)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/proposal proposal
|
||||
:wallet-connect/proposal-metadata metadata)
|
||||
:show-wallet-connect-sheet nil}))
|
||||
|
||||
(rf/defn session-connected
|
||||
{:events [:wallet-connect/created]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (merge (types/js->clj session) {:wc-version 2})
|
||||
client (get db :wallet-connect/client)]
|
||||
(log/debug "[wallet connect] session created - " session)
|
||||
{:show-wallet-connect-success-sheet nil
|
||||
:db (assoc db
|
||||
:wallet-connect/session-connected session
|
||||
:wallet-connect/sessions (types/js->clj
|
||||
(.-values
|
||||
(.-session
|
||||
client))))}))
|
||||
|
||||
(rf/defn manage-app
|
||||
{:events [:wallet-connect/manage-app]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (types/js->clj session)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/session-managed session
|
||||
:wallet-connect/showing-app-management-sheet? true)
|
||||
:show-wallet-connect-app-management-sheet nil}))
|
||||
|
||||
(rf/defn request-handler
|
||||
{:events [:wallet-connect/request]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [request (types/js->clj request-event)
|
||||
params (:request request)
|
||||
pending-requests (or (:wallet-connect/pending-requests db) [])
|
||||
new-pending-requests (conj pending-requests request)
|
||||
client (get db :wallet-connect/client)
|
||||
topic (:topic request)]
|
||||
{:db (assoc db :wallet-connect/pending-requests new-pending-requests)
|
||||
:dispatch [:wallet-connect/request-received request]}))
|
||||
|
||||
(rf/defn request-handler-test
|
||||
{:events [:wallet-connect/request-test]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:show-wallet-connect-sheet nil})
|
||||
|
||||
(defn subscribe-to-events
|
||||
[^js wallet-connect-client]
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-request-event)
|
||||
#(re-frame/dispatch [:wallet-connect/request %]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-created-event)
|
||||
#(re-frame/dispatch [:wallet-connect/created %]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-deleted-event)
|
||||
#(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-updated-event)
|
||||
#(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-proposal-event)
|
||||
#(re-frame/dispatch [:wallet-connect/proposal %])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-init
|
||||
(fn []
|
||||
(wallet-connect/init
|
||||
#(re-frame/dispatch [:wallet-connect/client-init %])
|
||||
#(log/error "[wallet-connect]" %))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-subscribe-to-events
|
||||
(fn [client]
|
||||
(subscribe-to-events client)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-approve-proposal
|
||||
(fn [[client proposal response]]
|
||||
(-> ^js client
|
||||
(.approve (clj->js {:proposal proposal :response response}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal approved"))
|
||||
(.catch #(log/error "[wallet-connect] session proposal approval error:" %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-reject-proposal
|
||||
(fn [[client proposal]]
|
||||
(-> ^js client
|
||||
(.reject (clj->js {:proposal proposal}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal rejected"))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-disconnect
|
||||
(fn [[client topic]]
|
||||
(-> ^js client
|
||||
(.disconnect (clj->js {:topic topic}))
|
||||
(.then #(log/debug "[wallet-connect] session disconnected - topic " topic))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-change-session
|
||||
(fn [[client topic accounts]]
|
||||
(-> ^js client
|
||||
(.update (clj->js {:topic topic
|
||||
:state {:accounts accounts}}))
|
||||
(.then #(log/debug "[wallet-connect] session topic " topic
|
||||
" changed to account " (first accounts)))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-pair
|
||||
(fn [[client uri]]
|
||||
(.pair client (clj->js {:uri uri}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-respond
|
||||
(fn [[client response]]
|
||||
(.respond client (clj->js response))))
|
||||
|
||||
(rf/defn approve-proposal
|
||||
{:events [:wallet-connect/approve-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)
|
||||
topic (:topic proposal)
|
||||
permissions (:permissions proposal)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids)))
|
||||
proposal-chain-ids)
|
||||
address (:address account)
|
||||
accounts (map #(str "eip155:" % ":" (address/normalized-hex address))
|
||||
supported-chain-ids)
|
||||
;; TODO: Check for unsupported
|
||||
metadata (get db :wallet-connect/proposal-metadata)
|
||||
response {:state {:accounts accounts}
|
||||
:metadata config/default-wallet-connect-metadata}]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-approve-proposal [client proposal response]}))
|
||||
|
||||
(rf/defn reject-proposal
|
||||
{:events [:wallet-connect/reject-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-reject-proposal client}))
|
||||
|
||||
(rf/defn change-session-account
|
||||
{:events [:wallet-connect/change-session-account]}
|
||||
[{:keys [db]} topic account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
sessions (get db :wallet-connect/sessions)
|
||||
session (first (filter #(= (:topic %) topic) sessions))
|
||||
permissions (:permissions session)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
address (:address account)
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids)))
|
||||
proposal-chain-ids)
|
||||
accounts (map #(str "eip155:" % ":" (address/normalized-hex address))
|
||||
supported-chain-ids)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/showing-app-management-sheet?
|
||||
false)
|
||||
:hide-wallet-connect-app-management-sheet nil
|
||||
:wc-2-change-session [client topic accounts]}))
|
||||
|
||||
(rf/defn disconnect-session
|
||||
{:events [:wallet-connect/disconnect]}
|
||||
[{:keys [db]} topic]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:hide-wallet-connect-app-management-sheet nil
|
||||
:hide-wallet-connect-success-sheet nil
|
||||
:wc-2-client-disconnect [client topic]
|
||||
:db (-> db
|
||||
(assoc :wallet-connect/sessions
|
||||
(types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(rf/defn pair-session
|
||||
{:events [:wallet-connect/pair]}
|
||||
[{:keys [db]} {:keys [data]}]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:db (assoc db :wallet-connect/scanned-uri data)
|
||||
:dispatch [:navigate-back]
|
||||
:wc-2-pair [client data]}))
|
||||
|
||||
(rf/defn wallet-connect-client-initate
|
||||
{:events [:wallet-connect/client-init]}
|
||||
[{:keys [db] :as cofx} ^js client]
|
||||
{:db (assoc db
|
||||
:wallet-connect/client client
|
||||
:wallet-connect/sessions (types/js->clj (.-values (.-session
|
||||
client))))
|
||||
:wc-2-subscribe-to-events client})
|
||||
|
||||
(rf/defn update-sessions
|
||||
{:events [:wallet-connect/update-sessions]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:db (-> db
|
||||
(assoc :wallet-connect/sessions (types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(rf/defn wallet-connect-complete-transaction
|
||||
{:events [:wallet-connect.dapp/transaction-on-result]}
|
||||
[{:keys [db]} message-id topic result]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
response {:topic topic
|
||||
:response {:jsonrpc "2.0"
|
||||
:id message-id
|
||||
:result result}}]
|
||||
{:db (assoc db :wallet-connect/response response)
|
||||
:wc-2-respond [client response]}))
|
||||
|
||||
(rf/defn wallet-connect-send-async
|
||||
[cofx {:keys [method params id] :as payload} message-id topic]
|
||||
(let [message? (browser/web3-sign-message? method)
|
||||
dapps-address (get-in cofx [:db :profile/profile :dapps-address])
|
||||
accounts (get-in cofx [:db :multiaccount/visible-accounts])
|
||||
typed? (and (not= constants/web3-personal-sign method)
|
||||
(not= constants/web3-eth-sign method))]
|
||||
(if (or message? (= constants/web3-send-transaction method))
|
||||
(let [[address data] (cond (and (= method constants/web3-keycard-sign-typed-data)
|
||||
(not (vector? params)))
|
||||
;; We don't use signer argument for keycard sign-typed-data
|
||||
["0x0" params]
|
||||
message? (browser/normalize-sign-message-params
|
||||
params
|
||||
typed?)
|
||||
:else [nil nil])]
|
||||
(when (or (not message?) (and address data))
|
||||
(signing/sign cofx
|
||||
(merge
|
||||
(if message?
|
||||
{:message {:address address
|
||||
:data data
|
||||
:v4 (= constants/web3-sign-typed-data-v4 method)
|
||||
:typed? typed?
|
||||
:pinless? (= method constants/web3-keycard-sign-typed-data)
|
||||
:from address}}
|
||||
{:tx-obj (-> params
|
||||
first
|
||||
(update :from #(or % dapps-address))
|
||||
(dissoc :gasPrice))})
|
||||
{:on-result [:wallet-connect.dapp/transaction-on-result message-id topic]
|
||||
:on-error [:wallet-connect.dapp/transaction-on-error message-id topic]}))))
|
||||
(when (#{"eth_accounts" "eth_coinbase"} method)
|
||||
(wallet-connect-complete-transaction
|
||||
cofx
|
||||
message-id
|
||||
topic
|
||||
(if (= method "eth_coinbase") dapps-address [dapps-address]))))))
|
||||
|
||||
(rf/defn wallet-connect-send-async-read-only
|
||||
[{:keys [db] :as cofx} {:keys [method] :as payload} message-id topic]
|
||||
(wallet-connect-send-async cofx payload message-id topic))
|
||||
|
||||
(rf/defn process-request
|
||||
{:events [:wallet-connect/request-received]}
|
||||
[{:keys [db] :as cofx} session-request]
|
||||
(let [pending-requests (get db :wallet-connect/pending-requests)
|
||||
{:keys [topic request]} session-request
|
||||
{:keys [id]} request]
|
||||
(wallet-connect-send-async-read-only cofx request id topic)))
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns status-im2.common.alert.events
|
||||
(ns status-im2.common.alert.effects
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn show-popup
|
||||
([title content]
|
||||
@@ -26,8 +26,7 @@
|
||||
(when on-dismiss
|
||||
{:cancelable false})))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:utils/show-popup
|
||||
(rf/reg-fx :effects.utils/show-popup
|
||||
(fn [{:keys [title content on-dismiss]}]
|
||||
(show-popup title content on-dismiss)))
|
||||
|
||||
@@ -50,8 +49,7 @@
|
||||
(or extra-options nil))
|
||||
{:cancelable false}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:utils/show-confirmation
|
||||
(rf/reg-fx :effects.utils/show-confirmation
|
||||
(fn [{:keys [title content confirm-button-text on-accept on-cancel cancel-button-text extra-options]}]
|
||||
(show-confirmation {:title title
|
||||
:content content
|
||||
@@ -60,18 +58,3 @@
|
||||
:on-accept on-accept
|
||||
:on-cancel on-cancel
|
||||
:extra-options extra-options})))
|
||||
|
||||
(defn show-question
|
||||
([title content on-accept]
|
||||
(show-question title content on-accept nil))
|
||||
([title content on-accept on-cancel]
|
||||
(rn/alert
|
||||
title
|
||||
content
|
||||
(vector (merge {:text (i18n/label :t/no)
|
||||
:accessibility-label :no-button}
|
||||
(when on-cancel {:onPress on-cancel}))
|
||||
{:text (i18n/label :t/yes)
|
||||
:onPress on-accept
|
||||
:accessibility-label :yes-button})
|
||||
nil)))
|
||||
@@ -1,8 +0,0 @@
|
||||
(ns status-im2.common.async-storage
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
react-native.async-storage))
|
||||
|
||||
(re-frame/reg-fx :async-storage-set (react-native.async-storage/set-item-factory))
|
||||
(re-frame/reg-fx :async-storage-get
|
||||
(fn [{ks :keys cb :cb}] (react-native.async-storage/get-items ks cb)))
|
||||
@@ -0,0 +1,11 @@
|
||||
(ns status-im2.common.async-storage.effects
|
||||
(:require
|
||||
[react-native.async-storage :as async-storage]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx :effects.async-storage/set
|
||||
(async-storage/set-item-factory))
|
||||
|
||||
(rf/reg-fx :effects.async-storage/get
|
||||
(fn [{ks :keys cb :cb}]
|
||||
(async-storage/get-items ks cb)))
|
||||
@@ -51,7 +51,7 @@
|
||||
(i18n/label :t/grant-face-id-permissions)
|
||||
(i18n/label :t/biometric-auth-error {:code code}))]
|
||||
(when handle-error?
|
||||
{:utils/show-popup
|
||||
{:effects.utils/show-popup
|
||||
{:title (i18n/label :t/biometric-auth-login-error-title)
|
||||
:content content}})))
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
(ns status-im2.common.font.effects
|
||||
(:require
|
||||
utils.image-server
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx :effects.font/get-font-file-for-initials-avatar
|
||||
(fn [callback]
|
||||
(utils.image-server/get-font-file-ready callback)))
|
||||
@@ -1,15 +1,9 @@
|
||||
(ns status-im2.common.font
|
||||
(ns status-im2.common.font.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
utils.image-server
|
||||
status-im2.common.font.effects
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:font/get-font-file-for-initials-avatar
|
||||
(fn [callback]
|
||||
(utils.image-server/get-font-file-ready callback)))
|
||||
|
||||
(rf/defn init-abs-root-path
|
||||
{:events [:font/init-font-file-for-initials-avatar]}
|
||||
[{:keys [db]} initials-avatar-font-file]
|
||||
@@ -0,0 +1,65 @@
|
||||
(ns status-im2.common.pairing.events
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.communities.discover.events]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn handle-local-pairing-signals
|
||||
[{:keys [db]} {:keys [type action data error] :as event}]
|
||||
(log/info "local pairing signal received"
|
||||
{:event event})
|
||||
(let [{:keys [account password]} data
|
||||
role (get-in db [:syncing :role])
|
||||
receiver? (= role constants/local-pairing-role-receiver)
|
||||
sender? (= role constants/local-pairing-role-sender)
|
||||
connection-success? (and (= type
|
||||
constants/local-pairing-event-connection-success)
|
||||
(= action
|
||||
constants/local-pairing-action-connect))
|
||||
error-on-pairing? (contains? constants/local-pairing-event-errors type)
|
||||
completed-pairing? (and (= type
|
||||
constants/local-pairing-event-transfer-success)
|
||||
(= action
|
||||
constants/local-pairing-action-pairing-installation))
|
||||
received-account? (and (= type
|
||||
constants/local-pairing-event-received-account)
|
||||
(= action
|
||||
constants/local-pairing-action-pairing-account)
|
||||
(and (some? account) (some? password)))
|
||||
multiaccount-data (when received-account?
|
||||
(merge account {:password password}))
|
||||
navigate-to-syncing-devices? (and (or connection-success? error-on-pairing?) receiver?)
|
||||
user-in-syncing-devices-screen? (or (= (:view-id db) :syncing-progress)
|
||||
(= (:view-id db) :syncing-progress-intro))
|
||||
user-in-sign-in-intro-screen? (= (:view-id db) :sign-in-intro)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
(assoc-in [:syncing :pairing-status] :connected)
|
||||
|
||||
received-account?
|
||||
(assoc-in [:syncing :profile] multiaccount-data)
|
||||
|
||||
error-on-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :error)
|
||||
|
||||
completed-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :completed))}
|
||||
(cond
|
||||
(and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||
{:dispatch (if user-in-sign-in-intro-screen?
|
||||
[:navigate-to-within-stack [:syncing-progress-intro :sign-in-intro]]
|
||||
[:navigate-to :syncing-progress])}
|
||||
|
||||
(and completed-pairing? sender?)
|
||||
{:dispatch [:syncing/clear-states]}
|
||||
|
||||
(and completed-pairing? receiver?)
|
||||
{:dispatch [:profile.login/local-paired-user]}
|
||||
|
||||
(and error-on-pairing? (some? error))
|
||||
{:dispatch [:toasts/upsert
|
||||
{:icon :i/alert
|
||||
:icon-color colors/danger-50
|
||||
:text error}]}))))
|
||||
@@ -38,10 +38,11 @@
|
||||
:padding-horizontal screen-padding
|
||||
:margin-vertical 12})
|
||||
|
||||
(def header-text
|
||||
(defn header-text
|
||||
[bottom-padding?]
|
||||
{:padding-horizontal screen-padding
|
||||
:padding-top 12
|
||||
:padding-bottom 8
|
||||
:padding-bottom (when bottom-padding? 8)
|
||||
:color colors/white})
|
||||
|
||||
(def header-sub-text
|
||||
@@ -53,7 +54,7 @@
|
||||
:margin-top 20})
|
||||
|
||||
(def scan-qr-code-container
|
||||
{:margin-top 19})
|
||||
{:margin-top 20})
|
||||
|
||||
(def qr-view-finder
|
||||
{:margin-horizontal screen-padding
|
||||
|
||||
@@ -35,13 +35,14 @@
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/header-text}
|
||||
:style (style/header-text (when subtitle true))}
|
||||
title]
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :regular
|
||||
:style style/header-sub-text}
|
||||
subtitle]])
|
||||
(when subtitle
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :regular
|
||||
:style style/header-sub-text}
|
||||
subtitle])])
|
||||
|
||||
(defn get-labels-and-on-press-method
|
||||
[]
|
||||
@@ -109,21 +110,22 @@
|
||||
[white-border :bottom-right]]])
|
||||
|
||||
(defn- viewfinder
|
||||
[qr-view-finder]
|
||||
[qr-view-finder helper-text?]
|
||||
(let [layout-size (+ (:width qr-view-finder) 2)]
|
||||
[rn/view {:style (style/viewfinder-container qr-view-finder)}
|
||||
[white-square layout-size]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:style style/viewfinder-text}
|
||||
(i18n/label :t/ensure-qr-code-is-in-focus-to-scan)]]))
|
||||
(when helper-text?
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:style style/viewfinder-text}
|
||||
(i18n/label :t/ensure-qr-code-is-in-focus-to-scan)])]))
|
||||
|
||||
(defn- scan-qr-code-tab
|
||||
[qr-view-finder]
|
||||
[qr-view-finder helper-text?]
|
||||
(if (and @camera-permission-granted?
|
||||
(boolean (not-empty qr-view-finder)))
|
||||
[viewfinder qr-view-finder]
|
||||
[viewfinder qr-view-finder helper-text?]
|
||||
[camera-permission-view]))
|
||||
|
||||
(defn- check-qr-code-and-navigate
|
||||
@@ -223,7 +225,7 @@
|
||||
[:<>
|
||||
[rn/view {:style style/scan-qr-code-container}]
|
||||
[qr-scan-hole-area qr-view-finder]])
|
||||
[scan-qr-code-tab @qr-view-finder]
|
||||
[scan-qr-code-tab @qr-view-finder (when subtitle true)]
|
||||
[rn/view {:style style/flex-spacer}]
|
||||
(when show-camera?
|
||||
[quo.theme/provider {:theme :light}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
(ns status-im.signals.core
|
||||
(ns status-im2.common.signals.events
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.ethereum.subscriptions :as ethereum.subscriptions]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.visibility-status-updates.core :as visibility-status-updates]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.common.pairing.events :as pairing]
|
||||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[status-im2.contexts.chat.messages.transport.events :as messages.transport]
|
||||
[status-im2.contexts.communities.discover.events]
|
||||
[status-im2.contexts.profile.login.events :as profile.login]
|
||||
[status-im2.contexts.push-notifications.local.events :as local-notifications]
|
||||
@@ -29,64 +28,6 @@
|
||||
[{:keys [db]} peer-stats]
|
||||
{:db (assoc db :peer-stats peer-stats :peers-count (count (:peers peer-stats)))})
|
||||
|
||||
(rf/defn handle-local-pairing-signals
|
||||
[{:keys [db]} {:keys [type action data error] :as event}]
|
||||
(log/info "local pairing signal received"
|
||||
{:event event})
|
||||
(let [{:keys [account password]} data
|
||||
role (get-in db [:syncing :role])
|
||||
receiver? (= role constants/local-pairing-role-receiver)
|
||||
sender? (= role constants/local-pairing-role-sender)
|
||||
connection-success? (and (= type
|
||||
constants/local-pairing-event-connection-success)
|
||||
(= action
|
||||
constants/local-pairing-action-connect))
|
||||
error-on-pairing? (contains? constants/local-pairing-event-errors type)
|
||||
completed-pairing? (and (= type
|
||||
constants/local-pairing-event-transfer-success)
|
||||
(= action
|
||||
constants/local-pairing-action-pairing-installation))
|
||||
received-account? (and (= type
|
||||
constants/local-pairing-event-received-account)
|
||||
(= action
|
||||
constants/local-pairing-action-pairing-account)
|
||||
(and (some? account) (some? password)))
|
||||
multiaccount-data (when received-account?
|
||||
(merge account {:password password}))
|
||||
navigate-to-syncing-devices? (and (or connection-success? error-on-pairing?) receiver?)
|
||||
user-in-syncing-devices-screen? (or (= (:view-id db) :syncing-progress)
|
||||
(= (:view-id db) :syncing-progress-intro))
|
||||
user-in-sign-in-intro-screen? (= (:view-id db) :sign-in-intro)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
(assoc-in [:syncing :pairing-status] :connected)
|
||||
|
||||
received-account?
|
||||
(assoc-in [:syncing :profile] multiaccount-data)
|
||||
|
||||
error-on-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :error)
|
||||
|
||||
completed-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :completed))}
|
||||
(cond
|
||||
(and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||
{:dispatch (if user-in-sign-in-intro-screen?
|
||||
[:navigate-to-within-stack [:syncing-progress-intro :sign-in-intro]]
|
||||
[:navigate-to :syncing-progress])}
|
||||
|
||||
(and completed-pairing? sender?)
|
||||
{:dispatch [:syncing/clear-states]}
|
||||
|
||||
(and completed-pairing? receiver?)
|
||||
{:dispatch [:profile.login/local-paired-user]}
|
||||
|
||||
(and error-on-pairing? (some? error))
|
||||
{:dispatch [:toasts/upsert
|
||||
{:icon :i/alert
|
||||
:icon-color colors/danger-50
|
||||
:text error}]}))))
|
||||
|
||||
(rf/defn process
|
||||
{:events [:signals/signal-received]}
|
||||
[{:keys [db] :as cofx} event-str]
|
||||
@@ -101,18 +42,18 @@
|
||||
"backup.performed" {:db (assoc-in db
|
||||
[:profile/profile :last-backup]
|
||||
(.-lastBackup event-js))}
|
||||
"envelope.sent" (transport.message/update-envelopes-status cofx
|
||||
(:ids
|
||||
(js->clj event-js
|
||||
:keywordize-keys
|
||||
true))
|
||||
:sent)
|
||||
"envelope.expired" (transport.message/update-envelopes-status cofx
|
||||
(:ids
|
||||
(js->clj event-js
|
||||
:keywordize-keys
|
||||
true))
|
||||
:not-sent)
|
||||
"envelope.sent" (messages.transport/update-envelopes-status cofx
|
||||
(:ids
|
||||
(js->clj event-js
|
||||
:keywordize-keys
|
||||
true))
|
||||
:sent)
|
||||
"envelope.expired" (messages.transport/update-envelopes-status cofx
|
||||
(:ids
|
||||
(js->clj event-js
|
||||
:keywordize-keys
|
||||
true))
|
||||
:not-sent)
|
||||
"message.delivered" (let [{:keys [chatID messageID]} (js->clj event-js
|
||||
:keywordize-keys
|
||||
true)]
|
||||
@@ -126,9 +67,9 @@
|
||||
"discovery.summary" (summary cofx (js->clj event-js :keywordize-keys true))
|
||||
"mediaserver.started" {:db (assoc db :mediaserver/port (.-port event-js))}
|
||||
"wakuv2.peerstats" (wakuv2-peer-stats cofx (js->clj event-js :keywordize-keys true))
|
||||
"messages.new" (transport.message/sanitize-messages-and-process-response cofx
|
||||
event-js
|
||||
true)
|
||||
"messages.new" (messages.transport/sanitize-messages-and-process-response cofx
|
||||
event-js
|
||||
true)
|
||||
"wallet" (ethereum.subscriptions/new-wallet-event cofx
|
||||
(js->clj event-js
|
||||
:keywordize-keys
|
||||
@@ -141,7 +82,7 @@
|
||||
"status.updates.timedout" (visibility-status-updates/handle-visibility-status-updates
|
||||
cofx
|
||||
(js->clj event-js :keywordize-keys true))
|
||||
"localPairing" (handle-local-pairing-signals
|
||||
"localPairing" (pairing/handle-local-pairing-signals
|
||||
cofx
|
||||
(js->clj event-js :keywordize-keys true))
|
||||
"curated.communities.update" (rf/dispatch [:fetched-contract-communities
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im2.common.standard-authentication.core
|
||||
(:require
|
||||
status-im2.common.standard-authentication.standard-auth.button.view
|
||||
status-im2.common.standard-authentication.password-input.view
|
||||
status-im2.common.standard-authentication.standard-auth.slide-button.view))
|
||||
|
||||
(def button status-im2.common.standard-authentication.standard-auth.button.view/view)
|
||||
(def password-input status-im2.common.standard-authentication.password-input.view/view)
|
||||
(def slide-button status-im2.common.standard-authentication.standard-auth.slide-button.view/view)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [on-enter-password button-label button-icon-left]}]
|
||||
[{:keys [on-enter-password on-press-biometrics button-label button-icon-left]}]
|
||||
(let [{:keys [key-uid customization-color] :as profile} (rf/sub [:profile/profile-with-image])
|
||||
{:keys [error processing password]} (rf/sub [:profile/login])
|
||||
sign-in-enabled? (rf/sub [:sign-in-enabled?])]
|
||||
@@ -32,20 +32,21 @@
|
||||
:customization-color customization-color
|
||||
:size 24}]]
|
||||
[password-input/view
|
||||
{:processing processing
|
||||
:error error
|
||||
:default-password password
|
||||
:sign-in-enabled? sign-in-enabled?}]
|
||||
[rn/view {:style style/enter-password-button}
|
||||
[quo/button
|
||||
{:size 40
|
||||
:type :primary
|
||||
:customization-color (or customization-color :primary)
|
||||
:accessibility-label :login-button
|
||||
:icon-left button-icon-left
|
||||
:disabled? (or (not sign-in-enabled?) processing)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
||||
(rf/dispatch [:profile.login/verify-database-password password
|
||||
#(on-enter-password password)]))}
|
||||
button-label]]]]]))
|
||||
{:on-press-biometrics on-press-biometrics
|
||||
:processing processing
|
||||
:error error
|
||||
:default-password password
|
||||
:sign-in-enabled? sign-in-enabled?}]
|
||||
[quo/button
|
||||
{:size 40
|
||||
:container-style style/enter-password-button
|
||||
:type :primary
|
||||
:customization-color (or customization-color :primary)
|
||||
:accessibility-label :login-button
|
||||
:icon-left button-icon-left
|
||||
:disabled? (or (not sign-in-enabled?) processing)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
||||
(rf/dispatch [:profile.login/verify-database-password password
|
||||
#(on-enter-password password)]))}
|
||||
button-label]]]]))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
(ns status-im2.common.standard-authentication.events
|
||||
(:require
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :standard-auth/on-biometric-success
|
||||
(fn [{:keys [db]} [callback]]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:keychain/get-user-password [key-uid callback]]]})))
|
||||
@@ -4,3 +4,7 @@
|
||||
{:margin-top 8
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def auth-button
|
||||
{:align-self :flex-end
|
||||
:margin-left 8})
|
||||
|
||||
@@ -27,21 +27,30 @@
|
||||
(rf/dispatch [:set-in [:profile/login :error] ""]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [default-password theme shell?]}]
|
||||
[{:keys [default-password theme shell? on-press-biometrics]}]
|
||||
(let [{:keys [error processing]} (rf/sub [:profile/login])
|
||||
error-message (get-error-message error)
|
||||
error? (boolean (seq error-message))]
|
||||
[:<>
|
||||
[quo/input
|
||||
{:type :password
|
||||
:blur? true
|
||||
:disabled? processing
|
||||
:placeholder (i18n/label :t/type-your-password)
|
||||
:auto-focus true
|
||||
:error? error?
|
||||
:label (i18n/label :t/profile-password)
|
||||
:on-change-text on-change-password
|
||||
:default-value (security/safe-unmask-data default-password)}]
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/input
|
||||
{:container-style {:flex 1}
|
||||
:type :password
|
||||
:blur? true
|
||||
:disabled? processing
|
||||
:placeholder (i18n/label :t/type-your-password)
|
||||
:auto-focus true
|
||||
:error? error?
|
||||
:label (i18n/label :t/profile-password)
|
||||
:on-change-text on-change-password
|
||||
:default-value (security/safe-unmask-data default-password)}]
|
||||
(when on-press-biometrics
|
||||
[quo/button
|
||||
{:container-style style/auth-button
|
||||
:on-press on-press-biometrics
|
||||
:icon-only? true
|
||||
:type :outline}
|
||||
:i/face-id])]
|
||||
(when error?
|
||||
[rn/view {:style style/error-message}
|
||||
[quo/info-message
|
||||
@@ -60,10 +69,7 @@
|
||||
:shell? shell?}]))}
|
||||
[rn/text
|
||||
{:style {:text-decoration-line :underline
|
||||
:color (colors/theme-colors
|
||||
(colors/custom-color :danger 50)
|
||||
(colors/custom-color :danger 60)
|
||||
theme)}
|
||||
:color (colors/resolve-color :danger theme)}
|
||||
:size :paragraph-2
|
||||
:suppress-highlighting true}
|
||||
(i18n/label :t/forgot-password)]]])]))
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.authorize
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[react-native.touch-id :as biometric]
|
||||
[status-im2.common.standard-authentication.enter-password.view :as enter-password]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn reset-password
|
||||
[]
|
||||
@@ -12,33 +14,49 @@
|
||||
(rf/dispatch [:set-in [:profile/login :error] ""]))
|
||||
|
||||
(defn authorize
|
||||
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
|
||||
[{:keys [biometric-auth? on-auth-success on-auth-fail on-close
|
||||
auth-button-label theme blur? auth-button-icon-left]}]
|
||||
(biometric/get-supported-type
|
||||
(fn [biometric-type]
|
||||
(if (and biometric-auth? biometric-type)
|
||||
(biometric/authenticate
|
||||
{:reason (i18n/label :t/biometric-auth-confirm-message)
|
||||
:on-success (fn [response]
|
||||
(when on-auth-success (on-auth-success response))
|
||||
(log/info "response" response))
|
||||
:on-fail (fn [error]
|
||||
(log/error "Authentication Failed. Error:" error)
|
||||
(when on-auth-fail (on-auth-fail error))
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password on-enter-password}])}]))})
|
||||
(do
|
||||
(reset-password)
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:on-close on-close
|
||||
:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password on-enter-password
|
||||
:button-icon-left auth-button-icon-left
|
||||
:button-label auth-button-label}])}]))))))
|
||||
(let [handle-auth-success (fn [biometric?]
|
||||
(fn [entered-password]
|
||||
(let [sha3-pwd (if biometric?
|
||||
(str (security/safe-unmask-data entered-password))
|
||||
(native-module/sha3 (str (security/safe-unmask-data
|
||||
entered-password))))]
|
||||
(on-auth-success sha3-pwd))))
|
||||
password-login (fn [{:keys [on-press-biometrics]}]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:on-close on-close
|
||||
:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password (handle-auth-success
|
||||
false)
|
||||
:on-press-biometrics on-press-biometrics
|
||||
:button-icon-left auth-button-icon-left
|
||||
:button-label auth-button-label}])}]))
|
||||
; biometrics-login recursively passes itself as a parameter because if the user
|
||||
; fails biometric auth they will be shown the password bottom sheet with an option
|
||||
; to retrigger biometric auth, so they can endlessly repeat this cycle.
|
||||
biometrics-login (fn [on-press-biometrics]
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(biometric/authenticate
|
||||
{:reason (i18n/label :t/biometric-auth-confirm-message)
|
||||
:on-success (fn [_response]
|
||||
(on-close)
|
||||
(rf/dispatch [:standard-auth/on-biometric-success
|
||||
(handle-auth-success true)]))
|
||||
:on-fail (fn [error]
|
||||
(on-close)
|
||||
(log/error "Authentication Failed. Error:" error)
|
||||
(when on-auth-fail (on-auth-fail error))
|
||||
(password-login {:on-press-biometrics
|
||||
#(on-press-biometrics
|
||||
on-press-biometrics)}))}))]
|
||||
(biometric/get-supported-type
|
||||
(fn [biometric-type]
|
||||
(if (and biometric-auth? biometric-type)
|
||||
(biometrics-login biometrics-login)
|
||||
(do
|
||||
(reset-password)
|
||||
(password-login {})))))))
|
||||
|
||||
@@ -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))
|
||||
@@ -4,17 +4,21 @@
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]))
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
track-text
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close (fn []
|
||||
(js/setTimeout
|
||||
#(reset! reset-slider? true)
|
||||
200))
|
||||
auth-method (rf/sub [:auth-method])
|
||||
biometric-auth? (= auth-method "biometric")]
|
||||
(fn [{:keys [track-text
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
@@ -32,7 +36,6 @@
|
||||
: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
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
(when chat-id
|
||||
(if-not (own-public-key? db chat-id)
|
||||
{:dispatch [:chat.ui/start-chat chat-id]}
|
||||
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/can-not-add-yourself)}})))
|
||||
{:effects.utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:content (i18n/label :t/can-not-add-yourself)}})))
|
||||
|
||||
(rf/defn handle-community-requests
|
||||
[cofx {:keys [community-id]}]
|
||||
|
||||
@@ -372,7 +372,9 @@
|
||||
;; wallet
|
||||
(def ^:const mainnet-chain-id 1)
|
||||
(def ^:const optimism-chain-id 10)
|
||||
(def ^:const optimism-test-chain-id 420)
|
||||
(def ^:const arbitrum-chain-id 42161)
|
||||
(def ^:const arbitrum-test-chain-id 421613)
|
||||
(def ^:const goerli-chain-id 5)
|
||||
|
||||
(def ^:const mainnet-short-name "eth")
|
||||
@@ -388,3 +390,6 @@
|
||||
(def ^:const account-default-customization-color :blue)
|
||||
|
||||
(def ^:const wallet-account-name-max-length 20)
|
||||
|
||||
(def ^:const status-address-domain ".stateofus.eth")
|
||||
(def ^:const eth-address-domain ".eth")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
(ns status-im2.contexts.add-new-contact.effects
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/reg-fx :effects.contacts/decompress-public-key
|
||||
(fn [{:keys [compressed-key on-success on-error]}]
|
||||
(native-module/compressed-key->public-key
|
||||
compressed-key
|
||||
constants/deserialization-key
|
||||
(fn [resp]
|
||||
(let [{:keys [error]} (transforms/json->clj resp)]
|
||||
(if error
|
||||
(on-error error)
|
||||
(on-success (str "0x" (subs resp 5)))))))))
|
||||
|
||||
(rf/reg-fx :effects.contacts/resolve-public-key-from-ens
|
||||
(fn [{:keys [chain-id ens on-success on-error]}]
|
||||
(ens/pubkey chain-id ens on-success on-error)))
|
||||
@@ -1,17 +1,13 @@
|
||||
(ns status-im2.contexts.add-new-contact.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im2.constants :as constants]
|
||||
status-im2.contexts.add-new-contact.effects
|
||||
[status-im2.contexts.contacts.events :as data-store.contacts]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.ens.stateofus :as stateofus]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]
|
||||
[utils.transforms :as transforms]
|
||||
[utils.validators :as validators]))
|
||||
|
||||
(defn init-contact
|
||||
@@ -108,14 +104,14 @@
|
||||
:empty {:db (dissoc db :contacts/new-identity)}
|
||||
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
|
||||
:decompress-key {:db (assoc db :contacts/new-identity contact)
|
||||
:contacts/decompress-public-key
|
||||
:effects.contacts/decompress-public-key
|
||||
{:compressed-key id
|
||||
:on-success
|
||||
(dispatcher :contacts/set-new-identity-success input)
|
||||
:on-error
|
||||
(dispatcher :contacts/set-new-identity-error input)}}
|
||||
:resolve-ens {:db (assoc db :contacts/new-identity contact)
|
||||
:contacts/resolve-public-key-from-ens
|
||||
:effects.contacts/resolve-public-key-from-ens
|
||||
{:chain-id (chain/chain-id db)
|
||||
:ens ens
|
||||
:on-success
|
||||
@@ -123,22 +119,7 @@
|
||||
:on-error
|
||||
(dispatcher :contacts/set-new-identity-error input)}})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:contacts/decompress-public-key
|
||||
(fn [{:keys [compressed-key on-success on-error]}]
|
||||
(native-module/compressed-key->public-key
|
||||
compressed-key
|
||||
constants/deserialization-key
|
||||
(fn [resp]
|
||||
(let [{:keys [error]} (transforms/json->clj resp)]
|
||||
(if error
|
||||
(on-error error)
|
||||
(on-success (str "0x" (subs resp 5)))))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:contacts/resolve-public-key-from-ens
|
||||
(fn [{:keys [chain-id ens on-success on-error]}]
|
||||
(ens/pubkey chain-id ens on-success on-error)))
|
||||
|
||||
(rf/defn build-contact
|
||||
{:events [:contacts/build-contact]}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.add-new-contact.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest are]]
|
||||
matcher-combinators.test
|
||||
[status-im2.contexts.add-new-contact.events :as events]))
|
||||
|
||||
(def user-ukey
|
||||
@@ -18,10 +19,10 @@
|
||||
;;; unit tests (no app-db involved)
|
||||
|
||||
(deftest validate-contact-test
|
||||
(are [i e] (= (events/validate-contact (events/init-contact
|
||||
{:user-public-key user-ukey
|
||||
:input i}))
|
||||
(events/init-contact e))
|
||||
(are [i e] (match? (events/validate-contact (events/init-contact
|
||||
{:user-public-key user-ukey
|
||||
:input i}))
|
||||
(events/init-contact e))
|
||||
|
||||
"" {:user-public-key user-ukey
|
||||
:input ""
|
||||
@@ -90,7 +91,7 @@
|
||||
|
||||
(deftest set-new-identity-test
|
||||
(with-redefs [events/dispatcher (fn [& args] args)]
|
||||
(are [i edb] (= (events/set-new-identity {:db db} i nil) edb)
|
||||
(are [i edb] (match? (events/set-new-identity {:db db} i nil) edb)
|
||||
|
||||
"" {:db db}
|
||||
|
||||
@@ -115,7 +116,7 @@
|
||||
:ens ens-stateofus-eth
|
||||
:public-key nil ; not yet...
|
||||
:state :resolve-ens}))
|
||||
:contacts/resolve-public-key-from-ens
|
||||
:effects.contacts/resolve-public-key-from-ens
|
||||
{:chain-id 1
|
||||
:ens ens-stateofus-eth
|
||||
:on-success [:contacts/set-new-identity-success ens]
|
||||
@@ -131,7 +132,7 @@
|
||||
:type :compressed-key
|
||||
:public-key nil ; not yet...
|
||||
:state :decompress-key}))
|
||||
:contacts/decompress-public-key
|
||||
:effects.contacts/decompress-public-key
|
||||
{:compressed-key user-ckey
|
||||
:on-success [:contacts/set-new-identity-success user-ckey]
|
||||
:on-error [:contacts/set-new-identity-error user-ckey]}})))
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns status-im2.contexts.add-new-contact.scan.scan-profile-qr-page
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im2.common.scan-qr-code.view :as scan-qr-code]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- f-internal-view
|
||||
[]
|
||||
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)]
|
||||
[:<>
|
||||
(when keyboard-shown
|
||||
(rn/dismiss-keyboard!))
|
||||
[scan-qr-code/view
|
||||
{:title (i18n/label :t/scan-qr)
|
||||
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity % %] 300)}]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:f> f-internal-view])
|
||||
@@ -4,7 +4,6 @@
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im2.contexts.add-new-contact.style :as style]
|
||||
[utils.address :as address]
|
||||
[utils.debounce :as debounce]
|
||||
@@ -96,8 +95,7 @@
|
||||
{:type :outline
|
||||
:icon-only? true
|
||||
:size 40
|
||||
:on-press #(rf/dispatch [::qr-scanner/scan-code
|
||||
{:handler :contacts/qr-code-scanned}])}
|
||||
:on-press #(rf/dispatch [:open-modal :scan-profile-qr-code])}
|
||||
:i/scan]]])
|
||||
(finally
|
||||
(rf/dispatch [:contacts/clear-new-identity]))))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.alert.events :as alert]
|
||||
[status-im2.common.alert.effects :as alert.effects]
|
||||
[status-im2.common.device-permissions :as device-permissions]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.chat.composer.actions.style :as style]
|
||||
@@ -146,7 +146,7 @@
|
||||
:on-denied
|
||||
#(js/setTimeout
|
||||
(fn []
|
||||
(alert/show-popup
|
||||
(alert.effects/show-popup
|
||||
(i18n/label :t/audio-recorder-error)
|
||||
(i18n/label
|
||||
:t/audio-recorder-permissions-error)
|
||||
@@ -198,9 +198,9 @@
|
||||
(reanimated/get-shared-value height)])
|
||||
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
|
||||
:on-denied (fn []
|
||||
(alert/show-popup (i18n/label :t/error)
|
||||
(i18n/label
|
||||
:t/external-storage-denied)))}))
|
||||
(alert.effects/show-popup (i18n/label :t/error)
|
||||
(i18n/label
|
||||
:t/external-storage-denied)))}))
|
||||
|
||||
(defn image-button
|
||||
[props animations insets edit]
|
||||
@@ -246,6 +246,6 @@
|
||||
[:f> send-button props state animations window-height images edit send-btn-opacity
|
||||
scroll-to-bottom-fn]
|
||||
(when (and (not edit) (not images))
|
||||
;; TODO(alwx): needs to be replaced with an `audio-button` later.
|
||||
;; See https://github.com/status-im/status-mobile/issues/16084 for more details.
|
||||
;; TODO(alwx): needs to be replaced with an `audio-button` later. See
|
||||
;; https://github.com/status-im/status-mobile/issues/16084 for more details.
|
||||
[:f> disabled-audio-button audio-btn-opacity])]))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user