Compare commits

..
Author SHA1 Message Date
Ibrahem Khalil 59553362d1 Merge branch 'develop' into 17116 2023-12-04 15:19:39 +02:00
Ibrkhalil 2f1ee972c2 Better syntax 2023-12-03 16:27:11 +02:00
Ibrkhalil 3b3743d7a7 Handle uniqueness 2023-12-03 16:26:00 +02:00
Ibrkhalil 3a1737b65e Bump go 2023-12-03 16:01:14 +02:00
Ibrkhalil 2b78d323dc clean 2023-12-03 15:45:45 +02:00
Ibrkhalil 79ee136826 Cater for sending community URL 2023-12-03 15:43:43 +02:00
Ibrkhalil bf3886ea18 Bump go 2023-12-03 13:04:54 +02:00
Ibrkhalil ff1068b53b Lint 2023-12-03 12:16:21 +02:00
Ibrahem Khalil 622df31a12 Change default value for loading? 2023-12-02 19:01:45 +02:00
Ibrahem Khalil ab8f65e6fa Merge branch 'develop' into 17116 2023-12-02 18:49:33 +02:00
Ibrkhalil 9674142fdc Bump go 2023-12-02 18:39:09 +02:00
Ibrkhalil e18ca22ff7 Add component 2023-12-02 18:37:24 +02:00
Ibrkhalil 31c226fcba Bump go and update endpoint 2023-12-02 11:17:50 +02:00
Ibrkhalil 292e3b7167 Bump go 2023-12-02 10:18:52 +02:00
Ibrkhalil 4c818ebaa6 Bump go 2023-12-02 10:15:07 +02:00
Ibrkhalil a83fa4df87 Improvements 2023-11-29 22:20:00 +02:00
Ibrkhalil 3782cd5808 clean 2023-11-29 21:57:59 +02:00
Ibrkhalil d1b094f986 Bump go 2023-11-29 21:57:00 +02:00
Ibrahem Khalil 6a8f061627 Merge branch 'develop' into 17116 2023-11-26 14:18:58 +02:00
Ibrkhalil eef9f45834 Add community invitation type 2023-11-26 14:18:16 +02:00
Ibrahem Khalil 865659552d Merge branch 'develop' into 17116 2023-11-21 19:52:22 +02:00
ibrkhalil 656e545957 Bump status-go 2023-11-21 19:48:06 +02:00
Ibrahem f9979a14c2 Test 2023-08-28 16:49:06 +03:00
211 changed files with 2899 additions and 4029 deletions
+1
View File
@@ -95,6 +95,7 @@ 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
@@ -1,4 +0,0 @@
{:linters
{:unresolved-symbol
{:exclude [(cljs.test/is [match? thrown-match?])
(clojure.test/is [match? thrown-match?])]}}}
-1
View File
@@ -32,7 +32,6 @@
"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,23 +27,18 @@ 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);
}
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
// 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
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
@@ -79,17 +74,4 @@ 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 "";
}
}
}
-20
View File
@@ -641,26 +641,6 @@ 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
-18
View File
@@ -602,15 +602,6 @@
}
},
{
"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",
@@ -755,15 +746,6 @@
}
},
{
"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",
-2
View File
@@ -65,7 +65,6 @@ 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
@@ -82,7 +81,6 @@ 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
-9
View File
@@ -14,7 +14,6 @@ stdenv.mkDerivation {
"patchJavaPhase"
"patchReactNativePhase"
"patchPodPhase"
"patchGlogPhase"
"installPhase"
];
@@ -99,14 +98,6 @@ 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;
-1
View File
@@ -73,7 +73,6 @@ 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
View File
@@ -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.26.2"
"shadow-cljs": "2.25.0"
},
"binary": {
"module_name": "status_nodejs_addon",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

+2 -4
View File
@@ -12,12 +12,10 @@
[metosin/malli "0.13.0"]
;; Dev dependencies
[refactor-nrepl "3.9.1"]
[cider/cider-nrepl "0.31.0"]
[refactor-nrepl "2.5.0"]
[cider/cider-nrepl "0.25.3"]
[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"]
+6 -54
View File
@@ -118,61 +118,13 @@
"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/contact-20 contact-20
:i/verified-20 verified-20
:i/untrustworthy-20 untrustworthy-20})
{: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})
(defn- append-to-keyword
[k & xs]
@@ -61,10 +61,14 @@
value (reagent/atom "")
focused? (atom false)]
(fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan on-detect-ens
on-detect-address address-regex valid-ens-or-address?]}]
on-detect-address
ens-regex address-regex
valid-ens-or-address?]}]
(let [on-change (fn [text]
(when (not= @value text)
(let [address? (when address-regex
(let [ens? (when ens-regex
(boolean (re-matches ens-regex text)))
address? (when address-regex
(boolean (re-matches address-regex text)))]
(if (> (count text) 0)
(reset! status :typing)
@@ -72,9 +76,9 @@
(reset! value text)
(when on-change-text
(on-change-text text))
(when (and on-detect-ens (> (count text) 0))
(when (and ens? on-detect-ens)
(reset! status :loading)
(on-detect-ens text #(reset! status :typing)))
(on-detect-ens text))
(when (and address? on-detect-address)
(reset! status :loading)
(on-detect-address text)))))
@@ -0,0 +1,35 @@
(ns quo.components.status-link-previews.community.component-spec
(:require
[quo.components.status-link-previews.community.view :as view]
[test-helpers.component :as h]))
(def props
{:title "Some title"
:description "Some description"
:link "status.im"
:logo "data:image/png,logo-x"
:thumbnail "data:image/png,whatever"
:member-count 20
:active-members-count 20})
(h/describe "Status link previews - Community"
(h/test "default render"
(h/render [view/view])
(h/is-truthy (h/query-by-label-text :link-preview))
(h/is-null (h/query-by-label-text :button-enable-preview)))
(h/test "renders with most common props"
(h/render [view/view props])
(h/is-truthy (h/query-by-text (:title props)))
(h/is-truthy (h/query-by-text (:description props)))
(h/is-truthy (h/query-by-text (:link props)))
(h/is-truthy (h/query-by-label-text :logo))
(h/is-truthy (h/query-by-label-text :thumbnail)))
(h/test "does not render thumbnail if prop is not present"
(h/render [view/view (dissoc props :thumbnail)])
(h/is-null (h/query-by-label-text :thumbnail)))
(h/test "does not render logo if prop is not present"
(h/render [view/view (dissoc props :logo)])
(h/is-null (h/query-by-label-text :logo))))
@@ -0,0 +1,51 @@
(ns quo.components.status-link-previews.community.style
(:require [quo.foundations.colors :as colors]))
(defn loading-circle
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 16
:height 16
:border-radius 16})
(defn loading-stat
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 32
:height 8
:border-radius 16})
(def loading-stat-container {:flex-direction :row :align-items :center :margin-right 12})
(defn loading-first-line-bar
[theme]
{:style {:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 145
:height 16
:border-radius 6}})
(defn loading-second-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 112
:height 8
:border-radius 6
:margin-bottom 17})
(defn loading-thumbnail-box
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 271
:height 139
:border-radius 16})
(def thumbnail
{:width "100%"
:height 139
:margin-top 8
:border-radius 12})
(def row-spacing {:flex-direction :row :margin-bottom 12})
@@ -0,0 +1,101 @@
(ns quo.components.status-link-previews.community.view
(:require
[quo.components.community.community-stat.view :as community-stat]
[quo.components.links.link-preview.style :as style]
[quo.components.markdown.text :as text]
[quo.components.status-link-previews.community.style :as status-link-previews-style]
[quo.theme :as theme]
[react-native.core :as rn]))
(defn- description-comp
[description members-count active-members-count]
[rn/view
[text/text
{:size :paragraph-2
:number-of-lines 3
:accessibility-label :description} description]
[rn/view {:flex-direction :row :margin-top 12}
[community-stat/view
{:value members-count
:icon :i/members
:accessibility-label :members-count
:style {:margin-right 12}}]
[community-stat/view
{:value (or active-members-count 0)
:icon :i/active-members
:accessibility-label :active-members-count}]]])
(defn- title-comp
[title]
[text/text
{:size :paragraph-1
:number-of-lines 1
:weight :semi-bold
:style style/title
:accessibility-label :title}
title])
(defn- thumbnail-comp
[thumbnail]
[rn/image
{:style status-link-previews-style/thumbnail
:source (if (string? thumbnail)
{:uri thumbnail}
thumbnail)
:accessibility-label :thumbnail}])
(defn- logo-comp
[logo]
[rn/image
{:accessibility-label :logo
:source (if (string? logo)
{:uri logo}
logo)
:style style/logo}])
(defn- stat-loading
[theme]
[rn/view {:style status-link-previews-style/loading-stat-container}
[rn/view {:style (status-link-previews-style/loading-circle theme)}]
[rn/view {:style (status-link-previews-style/loading-stat theme)}]])
(defn- loading-view
[theme]
[rn/view
{:accessibility-label :loading}
[rn/view {:style status-link-previews-style/row-spacing}
[rn/view (status-link-previews-style/loading-circle theme)]
[rn/view (status-link-previews-style/loading-first-line-bar theme)]]
[rn/view {:style (status-link-previews-style/loading-second-line-bar theme)}]
[rn/view status-link-previews-style/row-spacing
[stat-loading theme]
[stat-loading theme]]
[rn/view {:style (status-link-previews-style/loading-thumbnail-box theme)}]])
(defn f-internal-view
[{:keys [title description loading? thumbnail-size icon banner members-count active-members-count
theme on-press]
:or {loading? false}}]
[rn/touchable-opacity
{:style (merge (style/container (not loading?))
{:width 295
:height 245})
:accessibility-label :link-preview
:on-press on-press}
(if loading?
[loading-view theme]
[:<>
[rn/view {:style style/header-container}
(when icon
[logo-comp icon])
[title-comp title]]
(when description
[description-comp description members-count active-members-count])
(when banner
[thumbnail-comp banner thumbnail-size])])])
(defn- internal-view
[props]
[:f> f-internal-view props])
(def view (theme/with-theme internal-view))
-1
View File
@@ -107,4 +107,3 @@
[tag-resources size type resource icon-color label text-color labelled?]]]))
(def tag (quo.theme/with-theme tag-internal))
@@ -1,68 +0,0 @@
(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))))))
@@ -1,30 +0,0 @@
(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)))
@@ -1,57 +0,0 @@
(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))
@@ -1,99 +0,0 @@
(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))))
@@ -1,9 +0,0 @@
(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})
@@ -1,69 +0,0 @@
(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/resolve-color (:customization-color props) theme)})))
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
(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/resolve-color (:customization-color props) theme)})))
:backgroundColor (colors/custom-color (:customization-color props) 60)})))
(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/resolve-color (:customization-color props) theme)})))
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
(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/resolve-color :success theme)})))
:backgroundColor colors/success-50})))
(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/resolve-color :danger theme)})))
:backgroundColor colors/danger-50})))
(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/resolve-color :danger theme)}))))
:backgroundColor colors/danger-60}))))
@@ -3,48 +3,31 @@
[quo.foundations.colors :as colors]))
(defn- border-and-background-color
[customization-color theme]
[customization-color]
{: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/resolve-color :success theme)}
:background-color (colors/custom-color :success 50)}
:finalized {:border-color colors/neutral-80-opa-5
:background-color (colors/resolve-color customization-color theme)}
:background-color (colors/custom-color customization-color 50)}
:error {:border-color colors/neutral-80-opa-5
:background-color (colors/resolve-color :danger theme)}}
:background-color (colors/custom-color :danger 50)}}
:dark {:pending {:border-color colors/neutral-70
:background-color colors/neutral-80}
:confirmed {:border-color colors/white-opa-5
:background-color (colors/resolve-color :success theme)}
:background-color (colors/custom-color :success 60)}
:finalized {:border-color colors/neutral-80-opa-5
:background-color (colors/resolve-color customization-color theme)}
:background-color (colors/custom-color customization-color 60)}
:error {:border-color colors/white-opa-5
:background-color (colors/resolve-color :danger theme)}}})
(def max-value 100)
:background-color (colors/custom-color :danger 60)}}})
(defn root-container
[{: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)]
[{:keys [customization-color state theme]}]
(let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color)
[theme state])]
{:height 12
:margin-top -1
:width (str progress "%")
:width 8
:border-radius 3
:border-width 1
:border-color border-color
:background-color background-color}))
@@ -5,11 +5,9 @@
[react-native.core :as rn]))
(defn- view-internal
[{:keys [full-width?] :as props}]
[props]
[rn/view
{:accessibility-label :progress-bar
:style (style/root-container props)}
(when full-width?
[rn/view {:style (style/progressed-bar props)}])])
:style (style/root-container props)}])
(def view (quo.theme/with-theme view-internal))
@@ -4,7 +4,7 @@
(defn container
[networks? theme]
{:width "100%"
{:width 335
:height (if networks? 90 56)
:border-radius 16
:border-width 1
@@ -6,14 +6,14 @@
(h/describe "Wallet: Token Input"
(h/test "Token label renders"
(h/render [token-input/view
{:token {:symbol "snt"}
{:token :snt
:currency :eur
:conversion 1}])
(h/is-truthy (h/get-by-text "SNT")))
(h/test "Amount renders"
(h/render [token-input/view
{:token {:symbol "snt"}
{:token :snt
:currency :eur
:conversion 1}])
(h/is-truthy (h/get-by-text "€0.00"))))
@@ -43,7 +43,7 @@
:align-items :flex-end}}
[rn/image
{:style style/token
:source (resources/get-token (keyword (string/lower-case token)))}]
:source (resources/get-token token)}]
[rn/text-input
(cond-> {:auto-focus true
:ref #(reset! input-ref %)
@@ -1,200 +0,0 @@
(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))))
@@ -1,38 +0,0 @@
(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)})
@@ -1,187 +0,0 @@
(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))
+4 -6
View File
@@ -125,6 +125,7 @@
quo.components.settings.settings-item.view
quo.components.share.qr-code.view
quo.components.share.share-qr-code.view
quo.components.status-link-previews.community.view
quo.components.switchers.group-messaging-card.view
quo.components.tabs.account-selector
quo.components.tabs.segmented-tab
@@ -141,13 +142,11 @@
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
@@ -156,7 +155,6 @@
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))
@@ -284,6 +282,9 @@
(def url-preview quo.components.links.url-preview.view/view)
(def url-preview-list quo.components.links.url-preview-list.view/view)
;;;; Status links
(def status-link-preview-community quo.components.status-link-previews.community.view/view)
;;;; List items
(def account-item quo.components.list-items.account.view/view)
(def account-list-card quo.components.list-items.account-list-card.view/view)
@@ -386,14 +387,12 @@
(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)
@@ -404,5 +403,4 @@
(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)
-3
View File
@@ -77,11 +77,9 @@
[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]
@@ -89,7 +87,6 @@
[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]))
+5 -6
View File
@@ -285,6 +285,10 @@
(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]
@@ -296,12 +300,7 @@
suffix (get-from-colors-map suffix)
opacity (alpha (/ opacity 100))))))
(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 resolve-color (memoize resolve-color*))
(def ^{:deprecated true :superseded-by "resolve-color"}
custom-color
+84 -45
View File
@@ -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]
@@ -147,15 +147,48 @@
preferred-name (get-in db [:profile/profile :preferred-name])
emoji? (message-content/emoji-only-content? {:text input-text
:response-to message-id})]
{:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))})))
{:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))
:status-link-previews (map (fn [item]
{:url (:url item)
:community
{:community-id (get-in item [:community :community-id])
:color (get-in item
[:community :color])
:description (get-in item
[:community :description])
:display-name (get-in item
[:community :display-name])
:members-count (get-in item
[:community :members-count])
:active-members-count (get-in item
[:community :active-members-count])
:icon {:data-uri (get-in item
[:community :icon
:data-uri])
:width (get-in item
[:community :icon
:width])
:height (get-in item
[:community :icon
:height])}
:banner {:data-uri (get-in item
[:community :banner
:data-uri])
:width (get-in item
[:community :banner
:width])
:height (get-in item
[:community :banner
:height])}}})
(get-in db [:chat/status-link-previews :unfurled]))})))
(defn build-image-messages
[{db :db} chat-id input-text]
@@ -193,6 +226,7 @@
(rf/merge cofx
(clean-input current-chat-id)
(link-preview/reset-unfurled)
(link-preview/clear-status-link-previews)
(mentions/clear-mentions))))
(rf/defn send-messages
@@ -205,7 +239,8 @@
(rf/merge cofx
(clean-input (:current-chat-id db))
(link-preview/reset-unfurled)
(messages.transport/send-chat-messages messages)))))
(link-preview/clear-status-link-previews)
(chat.message/send-messages messages)))))
(rf/defn send-audio-message
[{:keys [db] :as cofx} audio-path duration current-chat-id]
@@ -214,51 +249,55 @@
(when-not (string/blank? audio-path)
(rf/merge
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :responding-to-message] nil)}
(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}))])))))
(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})))))))
(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)))
(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"})}])))
(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"})})))
(rf/defn send-edited-message
[{:keys [db]
:as cofx} text {:keys [message-id quoted-message chat-id]}]
(rf/merge
cofx
{:json-rpc/call [{:method "wakuext_editMessage"
:params [{:id message-id
:text text
:content-type (if (message-content/emoji-only-content?
{:text text
:response-to quoted-message})
constants/content-type-emoji
constants/content-type-text)
:linkPreviews (map #(-> %
(select-keys [:url :title :description
:thumbnail])
data-store-messages/->link-preview-rpc)
(get-in db [:chat/link-previews :unfurled]))}]
:js-response true
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result]))}]}
{:json-rpc/call
[{:method "wakuext_editMessage"
:params [{:id message-id
:text text
:content-type (if (message-content/emoji-only-content?
{:text text
:response-to quoted-message})
constants/content-type-emoji
constants/content-type-text)
:linkPreviews (map #(-> %
(select-keys [:url :title :description
:thumbnail])
data-store-messages/->link-preview-rpc)
(get-in db [:chat/link-previews :unfurled]))
:statusLinkPreviews (map
data-store-messages/<-status-link-previews-rpc
(get-in db [:chat/status-link-previews :unfurled]))}]
:js-response true
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result]))}]}
(link-preview/reset-unfurled)
(link-preview/clear-status-link-previews)
(cancel-message-edit)))
(rf/defn send-current-message
-1
View File
@@ -45,7 +45,6 @@
{: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]
+15
View File
@@ -5,6 +5,7 @@
[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]
@@ -20,6 +21,12 @@
[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]
@@ -138,6 +145,14 @@
: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]
+18
View File
@@ -2,6 +2,7 @@
(: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]
@@ -62,6 +63,23 @@
(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
+46
View File
@@ -0,0 +1,46 @@
(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 %])}]})
+1 -2
View File
@@ -74,7 +74,6 @@
:adminSettings :admin-settings
:tokenPermissions :token-permissions
:communityTokensMetadata :tokens-metadata
:introMessage :intro-message
:muteTill :muted-till})
(update :admin-settings
set/rename-keys
@@ -327,7 +326,7 @@
(conj contacts user-pk)
contacts)]
(when (seq pks)
{:json-rpc/call [{:method "wakuext_shareCommunity"
{:json-rpc/call [{:method "wakuext_shareCommunityV2"
:params [{:communityId community-id
:users pks}]
:js-response true
+18
View File
@@ -0,0 +1,18 @@
(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 %)))))
+13
View File
@@ -0,0 +1,13 @@
(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)))
+9
View File
@@ -85,3 +85,12 @@
(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))
+17 -2
View File
@@ -5,7 +5,8 @@
[utils.re-frame :as rf]))
(defn ->rpc
[{:keys [content] :as message}]
[{:keys [content]
:as message}]
(cond-> message
content
(assoc :text (:text content)
@@ -16,6 +17,18 @@
:community-id :communityId
:clock-value :clock})))
(defn- <-status-link-previews-rpc
[preview]
(-> preview
(update :community
set/rename-keys
{:communityId :community-id
:displayName :display-name
:membersCount :members-count
:activeMembersCount :active-members-count})
(update-in [:community :banner] set/rename-keys {:dataUri :data-uri})
(update-in [:community :icon] set/rename-keys {:dataUri :data-uri})))
(defn- <-link-preview-rpc
[preview]
(update preview :thumbnail set/rename-keys {:dataUri :data-uri}))
@@ -53,8 +66,10 @@
:new :new?
:albumImagesCount :album-images-count
:displayName :display-name
:linkPreviews :link-previews})
:linkPreviews :link-previews
:statusLinkPreviews :status-link-previews})
(update :link-previews #(map <-link-preview-rpc %))
(update :status-link-previews #(map <-status-link-previews-rpc %))
(update :quoted-message
set/rename-keys
{:parsedText :parsed-text
+14 -19
View File
@@ -91,11 +91,11 @@
{:chainId :chain-id
:removed :removed?})
name-details)]
{:db (reduce (fn [db {:keys [username removed? chain-id] :as name-detail}]
{:db (reduce (fn [db {:keys [username removed?] :as name-detail}]
(if removed?
(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)))))
(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)))))
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)
chain-id (chain/chain-id db)
names (get-in db [:ens/names chain-id] [])]
names (get-in db [:ens/names] [])
chain-id (chain/chain-id db)]
(rf/merge cofx
(cond-> {:dispatch-n [[:ens/update-usernames [{:username name :chain-id chain-id}]]]}
connected? (assoc :json-rpc/call
@@ -240,8 +240,7 @@
{:events [::set-username-candidate]}
[{:keys [db]} username]
(let [{:keys [custom-domain?]} (:ens/registration db)
chain-id (chain/chain-id db)
usernames (into #{} (keys (get-in db [:ens/names chain-id])))
usernames (into #{} (keys (get-in db [:ens/names])))
state (state custom-domain? username usernames)]
(reset! resolve-last-id (random/id))
(merge
@@ -311,23 +310,20 @@
(rf/defn store-name-address
{:events [::address-resolved]}
[{:keys [db]} username address]
(let [chain-id (chain/chain-id db)]
{:db (assoc-in db [:ens/names chain-id username :address] address)}))
{:db (assoc-in db [:ens/names username :address] address)})
(rf/defn store-name-public-key
{:events [::public-key-resolved]}
[{:keys [db]} username public-key]
(let [chain-id (chain/chain-id db)]
{:db (assoc-in db [:ens/names chain-id username :public-key] public-key)}))
{:db (assoc-in db [:ens/names username :public-key] public-key)})
(rf/defn store-expiration-date
{:events [::get-expiration-time-success]}
[{:keys [now db]} username timestamp]
(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)))}))
{:db (-> db
(assoc-in [:ens/names username :expiration-date]
(datetime/timestamp->year-month-day-date timestamp))
(assoc-in [:ens/names username :releasable?] (<= timestamp now)))})
(rf/defn navigate-to-name
{:events [::navigate-to-name]}
@@ -356,8 +352,7 @@
(rf/defn remove-username
{:events [::remove-username]}
[{:keys [db] :as cofx} name]
(let [chain-id (chain/chain-id db)
names (get-in db [:ens/names chain-id] [])
(let [names (get-in db [:ens/names] [])
preferred-name (get-in db [:profile/profile :preferred-name])
new-names (remove #(= name %) (keys names))
{:keys [chain-id username]} (get-in names [name])]
+9 -5
View File
@@ -15,6 +15,8 @@
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
@@ -30,7 +32,9 @@
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
@@ -41,12 +45,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]
@@ -132,7 +136,7 @@
(rf/defn on-return-from-background
[{:keys [db now] :as cofx}]
(let [new-account? (get db :onboarding/new-account?)
(let [new-account? (get db :onboarding-2/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
@@ -190,9 +194,9 @@
(rf/merge cofx
(cond
(= :chat view-id)
{: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)}
{: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)})
+23 -23
View File
@@ -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})
:effects.utils/show-popup {:title ""
:content (i18n/label :t/pin-changed)}}
{:db (assoc-in db
[:keycard :pin]
{:status nil
:login pin
:confirmation []
:error-label nil})
: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})
:effects.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})
: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})
:effects.utils/show-popup {:title ""
:content (i18n/label :t/pairing-changed)}}
{:db (assoc-in db
[:keycard :pin]
{:status nil
:pairing-code nil
:error-label nil})
:utils/show-popup {:title ""
:content (i18n/label :t/pairing-changed)}}
(common/hide-connection-sheet)
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
+4 -4
View File
@@ -293,14 +293,14 @@
(rf/defn show-wrong-keycard-alert
[_]
(log/debug "show-wrong-keycard-alert")
{:effects.utils/show-popup {:title (i18n/label :t/wrong-card)
:content (i18n/label :t/wrong-card-text)}})
{:utils/show-popup {:title (i18n/label :t/wrong-card)
:content (i18n/label :t/wrong-card-text)}})
(rf/defn unauthorized-operation
[cofx]
(rf/merge cofx
{:effects.utils/show-popup {:title ""
:content (i18n/label :t/keycard-unauthorized-operation)}}
{: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])))
+10 -11
View File
@@ -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)
:effects.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)
: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,11 +548,10 @@
(rf/defn show-no-keycard-applet-alert
[_]
{: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}})
{: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.
+2 -2
View File
@@ -35,8 +35,8 @@
(do
(log/debug (str "Cannot start keycard installation from state: " card-state))
(rf/merge cofx
{:effects.utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/something-went-wrong)}}
{: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
+9 -7
View File
@@ -11,6 +11,7 @@
[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]
@@ -220,12 +221,12 @@
(rf/defn on-backup-success
[{:keys [db] :as cofx} backup-type]
(rf/merge cofx
{: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))}}
{: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])
@@ -277,7 +278,7 @@
{:db (-> db
(assoc-in [:profile/profiles-overview key-uid :keycard-pairing] pairing)
(assoc :profile/login account)
(assoc :auth-method "none")
(assoc :auth-method keychain/auth-method-none)
(update :keycard dissoc :flow :migration-password)
(dissoc :recovered-account?))
::finish-migration [account settings password encryption-pass login-params]}))
@@ -372,3 +373,4 @@
cofx
{:on-card-connected :keycard/load-recovering-key-screen
:handler (common/dispatch-event :keycard/import-multiaccount)}))
+5 -4
View File
@@ -83,7 +83,7 @@
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:effects.utils/show-popup {:title ""
: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
:effects.utils/show-popup {:title ""
:utils/show-popup {:title ""
:content (i18n/label :t/something-went-wrong)}}
(common/clear-on-card-connected)
(navigation/navigate-to :keycard-settings nil)))
@@ -139,14 +139,15 @@
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:effects.utils/show-popup {:title (i18n/label (if keys-removed-from-card?
: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)
+3 -16
View File
@@ -194,7 +194,7 @@
{:events [:mailserver.ui/request-error-pressed]}
[{:keys [db]}]
(let [mailserver-error (:mailserver/request-error db)]
{:effects.utils/show-confirmation
{:utils/show-confirmation
{:title (i18n/label :t/mailserver-request-error-title)
:content (i18n/label :t/mailserver-request-error-content
{:error mailserver-error})
@@ -290,7 +290,8 @@
[{: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]))
@@ -412,17 +413,3 @@
(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))
+2 -1
View File
@@ -172,7 +172,8 @@
:use-mailservers? true
:recovered recovered}
config/default-multiaccount)
;; The address from which we derive any chat account/encryption keys
;; The address from which we derive any chat
;; account/encryption keys
eip1581-address
(assoc :eip1581-address eip1581-address)
save-mnemonic?
+1 -1
View File
@@ -31,7 +31,7 @@
(rf/merge cofx
{:set-root :progress
:chat.ui/clear-inputs nil
:effects.shell/reset-state nil
:shell/reset-state nil
:hide-popover nil
::logout nil
:profile.settings/webview-debug-changed false
+1 -1
View File
@@ -89,7 +89,7 @@
(rf/defn connect-failure
{:events [::connect-failure]}
[_ reason]
{:effects.utils/show-popup
{:utils/show-popup
{:title (i18n/label :t/error)
:content (str reason)}})
+2 -2
View File
@@ -165,9 +165,9 @@
(if (< (count (filter :enabled? (vals (get-in cofx [:db :pairing/installations]))))
(inc config/max-installations))
{:pairing/enable-installation [installation-id]}
{:effects.utils/show-popup {:title (i18n/label :t/pairing-maximum-number-reached-title)
{: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]}
+8 -8
View File
@@ -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]}
{:effects.utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (i18n/label :t/can-not-add-yourself)}}))
{: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
{: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])}})))
{: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]
:effects.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]
: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]}
@@ -1,12 +1,13 @@
(ns status-im2.common.signals.events
(ns status-im.signals.core
(: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.common.pairing.events :as pairing]
[status-im2.constants :as constants]
[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]
@@ -28,6 +29,64 @@
[{: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]
@@ -42,18 +101,18 @@
"backup.performed" {:db (assoc-in db
[:profile/profile :last-backup]
(.-lastBackup event-js))}
"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)
"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)
"message.delivered" (let [{:keys [chatID messageID]} (js->clj event-js
:keywordize-keys
true)]
@@ -67,9 +126,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" (messages.transport/sanitize-messages-and-process-response cofx
event-js
true)
"messages.new" (transport.message/sanitize-messages-and-process-response cofx
event-js
true)
"wallet" (ethereum.subscriptions/new-wallet-event cofx
(js->clj event-js
:keywordize-keys
@@ -82,7 +141,7 @@
"status.updates.timedout" (visibility-status-updates/handle-visibility-status-updates
cofx
(js->clj event-js :keywordize-keys true))
"localPairing" (pairing/handle-local-pairing-signals
"localPairing" (handle-local-pairing-signals
cofx
(js->clj event-js :keywordize-keys true))
"curated.communities.update" (rf/dispatch [:fetched-contract-communities
+3 -3
View File
@@ -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]
:effects.utils/show-popup {:title (i18n/label :t/sign-request-failed)
:content (:message error)}}
{:dispatch [:signing.ui/cancel-is-pressed]
:utils/show-popup {:title (i18n/label :t/sign-request-failed)
:content (:message error)}}
{:db (update db
:keycard assoc
:hash result
+2 -9
View File
@@ -60,17 +60,10 @@
{: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/current-names]
:<- [:ens/names]
(fn [[name ens]]
(let [{:keys [address public-key expiration-date releasable?]} (get ens name)
pending? (nil? address)]
@@ -86,7 +79,7 @@
(re-frame/reg-sub
:ens.main/screen
:<- [:ens/current-names]
:<- [:ens/names]
:<- [:profile/profile]
:<- [:ens/preferred-name]
:<- [:ens/registrations]
+1
View File
@@ -104,6 +104,7 @@
;;; Link previews
(reg-root-key-sub :link-previews-whitelist :link-previews-whitelist)
(reg-root-key-sub :chat/link-previews :chat/link-previews)
(reg-root-key-sub :chat/status-link-previews :chat/status-link-previews)
;;commands
(reg-root-key-sub :commands/select-account :commands/select-account)
+58
View File
@@ -0,0 +1,58 @@
(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,6 +1,5 @@
(ns status-im2.contexts.chat.messages.transport.events
(ns ^{:doc "Definition of the StatusMessage protocol"} status-im.transport.message.core
(:require
[clojure.set :as set]
[clojure.string :as string]
[status-im.browser.core :as browser]
[status-im.chat.models.message :as models.message]
@@ -21,7 +20,6 @@
[status-im2.contexts.chat.messages.pin.events :as messages.pin]
[status-im2.contexts.contacts.events :as models.contact]
[status-im2.contexts.shell.activity-center.events :as activity-center]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/defn process-next
@@ -349,58 +347,3 @@
cofx
(conj set-hash-fxs
#(sanitize-messages-and-process-response % response-js false)))))
(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 #(rf/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-emoji-reaction
{:events [:reactions/send-emoji-reaction]}
[{{:keys [current-chat-id]} :db} {:keys [message-id emoji-id]}]
{:json-rpc/call [{:method "wakuext_sendEmojiReaction"
:params [current-chat-id message-id emoji-id]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to send a reaction" %)}]})
(rf/defn send-retract-emoji-reaction
{:events [:reactions/send-emoji-reaction-retraction]}
[_ emoji-reaction-id]
{:json-rpc/call [{:method "wakuext_sendEmojiReactionRetraction"
:params [emoji-reaction-id]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to send a reaction retraction" %)}]})
@@ -0,0 +1,76 @@
(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- image->rpc [image] (set/rename-keys image {:data-uri :dataUri}))
(defn- link-preview->rpc
[preview]
(update preview
:thumbnail
(fn [thumbnail]
(image->rpc thumbnail))))
(defn- status-link-preview->rpc
[preview]
(update preview
:community
(fn [community]
(-> community
(set/rename-keys {:community-id :communityId
:display-name :displayName
:members-count :membersCount
:active-members-count :activeMembersCount})
(update :banner image->rpc)
(update :icon image->rpc)))))
(defn build-message
[msg]
(-> msg
(update :link-previews #(map link-preview->rpc %))
(update :status-link-previews #(set (map status-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
:status-link-previews :statusLinkPreviews
: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" %)}]})
+35
View File
@@ -0,0 +1,35 @@
(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})))
+18
View File
@@ -0,0 +1,18 @@
(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,11 +7,6 @@
[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
@@ -108,13 +103,7 @@
#(re-frame/dispatch
[:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)])
:accessory :switch
: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}]))
:active waku-bloom-filter-mode}]))
(defn- flat-list-data
[options]
@@ -56,7 +56,7 @@
{:events [::on-delete-profile-success]}
[cofx]
(log/info "[delete-profile] on-success")
{:effects.utils/show-popup
{:utils/show-popup
{:title (i18n/label :t/profile-deleted-title)
:content (i18n/label :t/profile-deleted-content)
:on-dismiss #(re-frame/dispatch [:logout])}})
@@ -46,8 +46,7 @@
:key :your-data-belongs-to-you-description}]
[react/view {:style styles/intro-button}
[quo/button
{:on-press #(do (re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])
(re-frame/dispatch [:profile.settings/mnemonic-was-shown]))}
{:on-press #(re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])}
(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/profile]))
customization-color (or (:color @(re-frame/subscribe [:onboarding-2/profile]))
@(re-frame/subscribe [:profile/customization-color key-uid]))
on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key
@@ -1,8 +1,10 @@
(ns status-im.ui.screens.wallet.send.views
(:require-macros [status-im.utils.views :as views])
(:require-macros [status-im.utils.views :refer [defview letsubs] :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]
@@ -127,6 +129,47 @@
" "
(: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}
+4
View File
@@ -6,6 +6,10 @@
[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"))
+6 -10
View File
@@ -7,6 +7,7 @@
[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]
@@ -37,11 +38,6 @@
{: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
@@ -50,7 +46,7 @@
build-version (str build/version " (" build-number ")")
separator (string/join (take 40 (repeat "-")))
[enode-id ip-address port]
(extract-url-components (:enode node-info))]
(transport.utils/extract-url-components (:enode node-info))]
(string/join
"\n"
(concat [(i18n/label :t/report-bug-email-template
@@ -72,7 +68,7 @@
(mapcat
(fn [{:keys [enode]}]
(let [[enode-id ip-address port]
(extract-url-components enode)]
(transport.utils/extract-url-components enode)]
[(str "id: " enode-id)
(str "ip: " ip-address)
(str "port: " port)
@@ -155,15 +151,15 @@
(rf/defn show-client-error
{:events [:show-client-error]}
[_]
{:effects.utils/show-popup {:title (i18n/label :t/cant-report-bug)
:content (i18n/label :t/mail-should-be-configured)}})
{: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)
:effects.utils/show-confirmation
:utils/show-confirmation
(cond-> {:title (i18n/label :t/send-logs)
:content (i18n/label :t/send-logs-to
{:email report-email})
+11
View File
@@ -0,0 +1,11 @@
(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?))))))
+120
View File
@@ -0,0 +1,120 @@
(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}))))
+31
View File
@@ -0,0 +1,31 @@
(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:"))
+5 -4
View File
@@ -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))
{:effects.utils/show-popup {:title (i18n/label :t/warning)
:content (i18n/label :t/account-is-used)}}
{: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
{:effects.utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/invalid-address-qr-code)}}))
{:utils/show-popup {:title (i18n/label :t/error)
:content (i18n/label :t/invalid-address-qr-code)}}))
(navigation/navigate-back))))
(re-frame/reg-fx
@@ -392,3 +392,4 @@
{:events [:wallet-legacy.accounts/share]}
[_ address]
{:list.selection/open-share {:message (eip55/address->checksum address)}})
@@ -7,6 +7,7 @@
[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]
@@ -172,7 +173,11 @@
(if (links/universal-link? uri)
{:dispatch [:universal-links/handle-url uri]}
{:browser/show-browser-selection uri})
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data 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})}))))
(rf/defn qr-scanner-result
{:events [:wallet-legacy.send/qr-scanner-result]}
+30 -11
View File
@@ -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]}
[_]
{:effects.async-storage/get {:keys [:buy-crypto-hidden]
:cb #(re-frame/dispatch [::store-buy-crypto-preference %])}})
{: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)
:effects.async-storage/set {:buy-crypto-hidden true}})
{:db (assoc db :wallet-legacy/buy-crypto-hidden true)
: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?]
{:effects.async-storage/set {:transactions-management-enabled? enabled?}
:db (assoc db :wallet-legacy/transactions-management-enabled? enabled?)})
{: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,9 +1072,10 @@
true])}))
2000)))
;;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]]
(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]]
(-> (js/Promise.all
(clj->js
[(js/Promise.
@@ -1082,6 +1083,24 @@
(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"
+2 -2
View File
@@ -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)
:effects.utils/show-popup {:content (i18n/label :t/contract-isnt-supported)}})
{:db (assoc-in db [:wallet-legacy/custom-token-screen :in-progress?] nil)
:utils/show-popup {:content (i18n/label :t/contract-isnt-supported)}})
(rf/defn add-custom-token
{:events [:wallet-legacy.custom-token.ui/add-pressed]}
+288
View File
@@ -0,0 +1,288 @@
(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.effects
(ns status-im2.common.alert.events
(:require
[re-frame.core :as re-frame]
[react-native.core :as rn]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.i18n :as i18n]))
(defn show-popup
([title content]
@@ -26,7 +26,8 @@
(when on-dismiss
{:cancelable false})))))
(rf/reg-fx :effects.utils/show-popup
(re-frame/reg-fx
:utils/show-popup
(fn [{:keys [title content on-dismiss]}]
(show-popup title content on-dismiss)))
@@ -49,7 +50,8 @@
(or extra-options nil))
{:cancelable false}))
(rf/reg-fx :effects.utils/show-confirmation
(re-frame/reg-fx
: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
@@ -58,3 +60,18 @@
: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)))
+8
View File
@@ -0,0 +1,8 @@
(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)))
@@ -1,11 +0,0 @@
(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)))
+1 -1
View File
@@ -51,7 +51,7 @@
(i18n/label :t/grant-face-id-permissions)
(i18n/label :t/biometric-auth-error {:code code}))]
(when handle-error?
{:effects.utils/show-popup
{:utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content content}})))
@@ -1,9 +1,15 @@
(ns status-im2.common.font.events
(ns status-im2.common.font
(:require
[clojure.string :as string]
status-im2.common.font.effects
[re-frame.core :as re-frame]
utils.image-server
[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]
-8
View File
@@ -1,8 +0,0 @@
(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)))
-65
View File
@@ -1,65 +0,0 @@
(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,11 +38,10 @@
:padding-horizontal screen-padding
:margin-vertical 12})
(defn header-text
[bottom-padding?]
(def header-text
{:padding-horizontal screen-padding
:padding-top 12
:padding-bottom (when bottom-padding? 8)
:padding-bottom 8
:color colors/white})
(def header-sub-text
@@ -54,7 +53,7 @@
:margin-top 20})
(def scan-qr-code-container
{:margin-top 20})
{:margin-top 19})
(def qr-view-finder
{:margin-horizontal screen-padding
+15 -17
View File
@@ -35,14 +35,13 @@
[quo/text
{:size :heading-1
:weight :semi-bold
:style (style/header-text (when subtitle true))}
:style style/header-text}
title]
(when subtitle
[quo/text
{:size :paragraph-1
:weight :regular
:style style/header-sub-text}
subtitle])])
[quo/text
{:size :paragraph-1
:weight :regular
:style style/header-sub-text}
subtitle]])
(defn get-labels-and-on-press-method
[]
@@ -110,22 +109,21 @@
[white-border :bottom-right]]])
(defn- viewfinder
[qr-view-finder helper-text?]
[qr-view-finder]
(let [layout-size (+ (:width qr-view-finder) 2)]
[rn/view {:style (style/viewfinder-container qr-view-finder)}
[white-square layout-size]
(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)])]))
[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 helper-text?]
[qr-view-finder]
(if (and @camera-permission-granted?
(boolean (not-empty qr-view-finder)))
[viewfinder qr-view-finder helper-text?]
[viewfinder qr-view-finder]
[camera-permission-view]))
(defn- check-qr-code-and-navigate
@@ -225,7 +223,7 @@
[:<>
[rn/view {:style style/scan-qr-code-container}]
[qr-scan-hole-area qr-view-finder]])
[scan-qr-code-tab @qr-view-finder (when subtitle true)]
[scan-qr-code-tab @qr-view-finder]
[rn/view {:style style/flex-spacer}]
(when show-camera?
[quo.theme/provider {:theme :light}
@@ -1,7 +1,7 @@
(ns status-im2.common.standard-authentication.core
(:require
status-im2.common.standard-authentication.password-input.view
status-im2.common.standard-authentication.standard-auth.button.view
status-im2.common.standard-authentication.standard-auth.slide-button.view))
(def password-input status-im2.common.standard-authentication.password-input.view/view)
(def button status-im2.common.standard-authentication.standard-auth.button.view/view)
(def slide-button status-im2.common.standard-authentication.standard-auth.slide-button.view/view)
@@ -9,7 +9,7 @@
[utils.re-frame :as rf]))
(defn view
[{:keys [on-enter-password on-press-biometrics button-label button-icon-left]}]
[{:keys [on-enter-password 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,21 +32,20 @@
:customization-color customization-color
:size 24}]]
[password-input/view
{: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]]]]))
{: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]]]]]))
@@ -1,8 +0,0 @@
(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,7 +4,3 @@
{:margin-top 8
:flex-direction :row
:align-items :center})
(def auth-button
{:align-self :flex-end
:margin-left 8})
@@ -27,30 +27,21 @@
(rf/dispatch [:set-in [:profile/login :error] ""]))
(defn- view-internal
[{:keys [default-password theme shell? on-press-biometrics]}]
[{:keys [default-password theme shell?]}]
(let [{:keys [error processing]} (rf/sub [:profile/login])
error-message (get-error-message error)
error? (boolean (seq error-message))]
[:<>
[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])]
[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)}]
(when error?
[rn/view {:style style/error-message}
[quo/info-message
@@ -69,7 +60,10 @@
:shell? shell?}]))}
[rn/text
{:style {:text-decoration-line :underline
:color (colors/resolve-color :danger theme)}
:color (colors/theme-colors
(colors/custom-color :danger 50)
(colors/custom-color :danger 60)
theme)}
:size :paragraph-2
:suppress-highlighting true}
(i18n/label :t/forgot-password)]]])]))
@@ -1,12 +1,10 @@
(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.security.core :as security]))
[utils.re-frame :as rf]))
(defn reset-password
[]
@@ -14,49 +12,33 @@
(rf/dispatch [:set-in [:profile/login :error] ""]))
(defn authorize
[{:keys [biometric-auth? on-auth-success on-auth-fail on-close
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
auth-button-label theme blur? auth-button-icon-left]}]
(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 {})))))))
(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}])}]))))))

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