Compare commits

..
Author SHA1 Message Date
jo-mut 31d0c14247 code refactor 2024-05-27 00:58:53 +02:00
Ajay Sivan 539b7bbff4 fix: white panel when the bottom sheet is launched 2024-05-27 00:55:59 +02:00
Jamie Caprani 777b2bb8da chore(wallet): smooth collectible list loading transition 2024-05-24 13:44:16 -07:00
Parvesh Monu f17484f61b fix missing pinned messages label (#20174) 2024-05-25 00:00:46 +05:30
Ulises Manuel 49a41f4787 [#19232] - Fix derivation path generation and keypair creation (#19531)
* Add more default dependencies to slide button

* Fix wallet account creation: derivation paths and keypairs
2024-05-24 10:03:02 -06:00
Siddarth Kumar f65c10502b pick between JSC & Hermes for Android (#20171)
We implement both `JSC` and `Hermes` in build phase of `Android` which increases our `APK` size by ~ `2 MB`.
This was fine before but currently we have to get below the `100 MB` limit.

This commit implements the preferred engine after inferring `hermesEnabled`  property from gradle.properties
This property is modified at build time for release here
https://github.com/status-im/status-mobile/blob/178d62bd276afffef5fe7a3f773e390d83336d9c/nix/mobile/android/build.nix#L17
and set for debug here
https://github.com/status-im/status-mobile/blob/178d62bd276afffef5fe7a3f773e390d83336d9c/Makefile#L280

Which should further reduce the `APK` size by `2 MB`.
2024-05-24 21:02:32 +05:30
flexsurfer e30ca97372 Remove not implemented Notification settings from community longtap m… (#20169) 2024-05-24 16:51:25 +02:00
Andrea Maria Piana 178d62bd27 Update eth-archival pokt url 2024-05-24 14:56:52 +01:00
Ajay Sivan 4262d0e8ab Avatars/dApp Avatar Component (#20145) 2024-05-24 05:48:43 -07:00
Ajay Sivan 6f3aa19a04 Avatars/Community Avatar Component (#20147) 2024-05-24 05:33:52 -07:00
Ajay Sivan c398c85b0f Avatars/Token Avatar Component (#20141) 2024-05-24 05:04:20 -07:00
Jamie Caprani 3a728fb112 chore(wallet): reset input on send flow when swapping accounts (#20099) 2024-05-24 13:31:34 +02:00
Omar Basem d2fb6c7ee0 fix: balances in network preferences after removing account (#20139)
fix: balances in network preferences after removing account (#20139)
2024-05-23 17:52:14 +04:00
BalogunofAfricaandBrian Sztamfater 2ffdeb1fa2 fix(wallets): no routes render on input amount (#20112)
* fix: no routes found error when disabling chains and current amount exceeds new max amount

* fix: disable button on routes loading

* add no-routes-found component

---------

Co-authored-by: Brian Sztamfater <brian@status.im>
2024-05-23 12:33:33 +01:00
flexsurfer a0d9134f7b Incorrect Button Label Color in Disabled State #20056 (#20156) 2024-05-23 12:38:03 +02:00
flexsurfer 81977475c5 support ios "15.3" (#20127) 2024-05-23 10:59:43 +02:00
flexsurfer 813e4ee730 Syncing/Sync failed screens are missing illustrations #20068 (#20142) 2024-05-23 10:54:38 +02:00
flexsurfer 5eba373c3c Feature/hide browser behind feature flag #20022 (#20082) 2024-05-23 10:12:39 +02:00
yqrashawn c19f170239 fix(dev exp): auto disable fast refresh on iOS (#20120) 2024-05-23 15:17:01 +08:00
Sean Hagstrom 60ef4fab4b Implement display of missing key pairs in wallet settings (#20094)
* fix: ensure the keypairs use blur for their theme

* fix: allow for container-style to be passed to standard-title component

* chore: add translations for for missing-keypair labels

* tweak: add support for missing-keypair type for drawer-top component

* tweak: add initial implementation of missing-keypair list-item component

* tweak: add initial implementation of missing-keypairs list component

* feature: add initial implementation of displaying missing key-pairs

* tweak: update missing-keypair list-item to support blur, light, and dark mode

* chore: add missing-keypair list-item preview

* chore: add missing-keypairs preview

* chore: decode :operable key in account to be keyword

* tweak: remove unneeded keyword decoding

* tweak: update drawer-top component to use keypair and stored field

* tidy: revert change for checking for not default-keypair in actions menu
2024-05-22 18:30:32 +01:00
flexsurfer 47b4ab923b Pinning contact request message leads to a crash #20131 (#20132) 2024-05-22 16:43:18 +02:00
Ajay Sivan 05a09d1fa1 Buttons/Swap-Order-Button Component (#20119) 2024-05-22 05:03:13 -07:00
John Ngei 8bd1c8de95 refactored some styles and fixed text alignment fix ens name verication 2024-05-22 11:11:36 +02:00
Ajay Sivan e5ab94f1b2 Wallet/Approval Label Component (#20117) 2024-05-22 00:59:46 -07:00
Omar Basem ff82d9c39e fix: update confirm button copy on input amount screen(#20122)
* fix: update confirm button copy on input amount screen(#20122)
2024-05-22 09:34:55 +04:00
Ulises Manuel e1210e90c0 [#19544] Show preselected networks in QR code (#20070)
* Add subscription to get preferred networks given an address
* Fix preselected networks in receive screen
* Improve subscription
* Fix preselected networks in share screen
* Update test to include oeth
2024-05-21 10:08:14 -06:00
Jamie Caprani ed88170c5d chore(wallet): hide share button on scanner pages except universal scanner 2024-05-21 08:11:04 -07:00
Brian Sztamfater 32123d2f69 fix: max value is incorrect for some tokens (#20096)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-05-21 11:59:19 -03:00
Yevheniia Berdnyk a480df4ef5 e2e: fixes 21.05 2024-05-21 16:50:58 +03:00
Anton Iakimov b3361b7d89 chore: drop wakuv2 fleets, use waku fleets
See https://github.com/status-im/infra-nim-waku/issues/91 for details

Mostly done automatically. Some parts manually.
https://github.com/status-im/status-go/compare/3103c298...92ef58d4

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2024-05-21 14:02:30 +02:00
Ajay Sivan f7163c748b Use data from API to populate the buy assets sheet (#20078)
Remove unused code & resources
2024-05-21 04:45:07 -07:00
Omar Basem 34cf65bfc9 fix: overlapping send details (#20102)
* fix: overlapping send details (#20102)
2024-05-21 11:19:22 +04:00
Icaro Motta 88afa09baf Only log event payload at trace level (#20097)
While investigating why login is slow
https://github.com/status-im/status-mobile/issues/20059 and when testing with
accounts with communities, I noticed we are logging huge payloads because they
include data URLs. This makes debugging the app harder.

Therefore, we will now log the full event payload only at the trace level, and
at the debug level we only log the event type.

This problem was first described by ulisesmac.
2024-05-20 23:06:38 -03:00
yqrashawn b358c06a31 fix: Community state cannot be changed to failed to fetch (#20101)
Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-05-21 09:16:05 +08:00
128 changed files with 2791 additions and 1472 deletions
-1
View File
@@ -36,5 +36,4 @@ STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=1
ENABLE_ALERT_BANNER=1
+8 -6
View File
@@ -83,7 +83,6 @@ def jscFlavor = 'org.webkit:android-jsc:+'
*/
def enableHermes = hermesEnabled.toBoolean();
def getCommitHash = { ->
if (project.hasProperty("commitHash")) {
return project.commitHash
@@ -278,11 +277,14 @@ dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("androidx.core:core-splashscreen:1.0.0")
// we don't use hermes for debug but we need its pom file for release builds
// https://github.com/status-im/status-mobile/pull/18675
implementation("com.facebook.react:hermes-android")
// FIXME: implementing both hermes & JSC increases bundle size by ~ 2MB
implementation(jscFlavor)
if (enableHermes) {
implementation("com.facebook.react:hermes-android")
} else {
// https://github.com/status-im/status-mobile/issues/18493
// we don't use hermes for debug builds because it crashes too often
implementation(jscFlavor)
}
// react-native-screens
implementation("androidx.appcompat:appcompat:1.1.0-rc01")
+2 -1
View File
@@ -55,7 +55,8 @@ com.android.tools.build:gradle:8.1.1
com.google.errorprone:error_prone_annotations:2.7.1
com.android.tools.lint:lint-gradle:31.1.1
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0
com.android.tools.build:gradle:3.5.4' \
com.android.tools.build:gradle:3.5.4
com.facebook.react:hermes-android:0.73.5' \
>> "${DEPS_LIST}"
}
+1 -1
View File
@@ -57,7 +57,7 @@ in {
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
openjdk = super.openjdk11_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
versions = ["15.1" "15.2"];
versions = ["15.1" "15.2" "15.3"];
};
go = super.go_1_20;
clang = super.clang_15;
+20 -37
View File
@@ -1,7 +1,7 @@
{
"meta": {
"hostname": "node-01.do-ams3.sites.misc",
"timestamp": "2024-02-02T14:48:22.521541",
"timestamp": "2024-03-15T00:00:36.865154",
"warning": "DO NOT EDIT! Auto generated from Consul. Should only be used at build time."
},
"fleets": {
@@ -82,38 +82,21 @@
"boot-01.ac-cn-hongkong-c.eth.staging": "/ip4/47.91.229.44/tcp/30703/ethv4/16Uiu2HAmRnt2Eyoknh3auxh4fJwkRgqkH1gqrWGes8Pk1k3MV4xu"
}
},
"wakuv2.prod": {
"waku.sandbox": {
"tcp/p2p/waku": {
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD"
"node-01.do-ams3.waku.sandbox": "/dns4/node-01.do-ams3.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE",
"node-01.gc-us-central1-a.waku.sandbox": "/dns4/node-01.gc-us-central1-a.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB",
"node-01.ac-cn-hongkong-c.waku.sandbox": "/dns4/node-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/30303/p2p/16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV"
},
"enr/p2p/waku": {
"node-01.do-ams3.wakuv2.prod": "enr:-P-4QJI8tS1WTdIQxq_yIrD05oIIW1Xg-tm_qfP0CHfJGnp9dfr6ttQJmHwTNxGEl4Le8Q7YHcmi-kXTtphxFysS11oBgmlkgnY0gmlwhLymh5GKbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi5wcm9kLnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDbl1X_zJIw3EAJGtmHMVn4Z2xhpSoUaP5ElsHKCv7hlWDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.prod": "enr:-QERuEC0EGWTjg_gYdnuPypJ9LAbB3lml6M8GiRajGegL2iWEj1MJzUMV9X6jXw7mMAQQLozLCTLFT-zv-ELQLPwWdACAYJpZIJ2NIJpcIQieWRsim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdXYyLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA_30kHgQqfXZRioa4J_u5asgXTJ5iw_8w3lEICH4TFu_g3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.prod": "enr:-QERuEDABor1lVmSa5ek8of5eBc8jZoxxdleJVLLdMl8UeZHNwhsVp64SFiCT4BRIIfcs7uxTPUCjmWxK_OA1s-FfIW7AYJpZIJ2NIJpcIQI0t7nim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdXYyLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAo0C-VvfgHiXrxZi3umDiooXMGY9FvYj5_d1Q4EeS7eyg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
"node-01.do-ams3.waku.sandbox": "enr:-QESuEB4Dchgjn7gfAvwB00CxTA-nGiyk-aALI-H4dYSZD3rUk7bZHmP8d2U6xDiQ2vZffpo45Jp7zKNdnwDUx6g4o6XAYJpZIJ2NIJpcIRA4VDAim11bHRpYWRkcnO4XAArNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwAtNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQOvD3S3jUNICsrOILlmhENiWAMmMVlAl6-Q8wRB7hidY4N0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.gc-us-central1-a.waku.sandbox": "enr:-QEkuEBIkb8q8_mrorHndoXH9t5N6ZfD-jehQCrYeoJDPHqT0l0wyaONa2-piRQsi3oVKAzDShDVeoQhy0uwN1xbZfPZAYJpZIJ2NIJpcIQiQlleim11bHRpYWRkcnO4bgA0Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwA2Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQKnGt-GSgqPSf3IAPM7bFgTlpczpMZZLF3geeoNNsxzSoN0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.ac-cn-hongkong-c.waku.sandbox": "enr:-QEkuEB3WHNS-xA3RDpfu9A2Qycr3bN3u7VoArMEiDIFZJ66F1EB3d4wxZN1hcdcOX-RfuXB-MQauhJGQbpz3qUofOtLAYJpZIJ2NIJpcIQI2SVcim11bHRpYWRkcnO4bgA0Ni9ub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwA2Ni9ub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQPK35Nnz0cWUtSAhBp7zvHEhyU_AqeQUlqzLiLxfP2L4oN0Y3CCdl-DdWRwgiMohXdha3UyDw"
},
"wss/p2p/waku": {
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA",
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD"
}
},
"wakuv2.test": {
"tcp/p2p/waku": {
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS",
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm"
},
"enr/p2p/waku": {
"node-01.do-ams3.wakuv2.test": "enr:-P-4QPLMQ1zIYRAs4-F0mYmMxMihSySRtEIuGHJ_Qd_GL8XqUE78hpVUE97rgwlXnxPkzMJHkWyiNq7DT1fdZSy3QcgBgmlkgnY0gmlwhIbRi9KKbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDnr03Tuo77930a7sYLikftxnuG3BbC3gCFhA4632ooDaDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.test": "enr:-QERuEDZcXS5tjppj4TIlOm-TLanjmqx3-uk2kGFvvAQR1NVrklUhiN1JCb5dWucEQ_oDADOb6nG_1mJ5goF5CHneZ-VAYJpZIJ2NIJpcIRomu-Aim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdXYyLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA1giYsmWV9r2yJZYAiMGHJfjLlLeqAuTAokUGPN__pkxg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.test": "enr:-QERuEC2LyiXKURIKxNHa7Mj7frsM-lZiAGJ-2mopR3w8LMn2UhKmahZ9RHKV5ehBN1fXbRYqAeiXuOxD9t2igF4PIizAYJpZIJ2NIJpcIQv8tJJim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdXYyLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAhAm-P4q6mWONKcGnbLPU8WXZJ4Qs3AxIbrycvc7PVKsg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
},
"wss/p2p/waku": {
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS",
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm"
"node-01.do-ams3.waku.sandbox": "/dns4/node-01.do-ams3.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmQSMNExfUYUqfuXWkD5DaNZnMYnigRxFKbk3tcEFQeQeE",
"node-01.gc-us-central1-a.waku.sandbox": "/dns4/node-01.gc-us-central1-a.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAm6fyqE1jB5MonzvoMdU8v76bWV8ZeNpncDamY1MQXfjdB",
"node-01.ac-cn-hongkong-c.waku.sandbox": "/dns4/node-01.ac-cn-hongkong-c.waku.sandbox.status.im/tcp/8000/wss/p2p/16Uiu2HAmSJvSJphxRdbnigUV5bjRRZFBhTtWFTSyiKaQByCjwmpV"
}
},
"waku.test": {
@@ -183,9 +166,9 @@
"boot-01.ac-cn-hongkong-c.shards.test": "/dns4/boot-01.ac-cn-hongkong-c.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmGwcE8v7gmJNEWFtZtojYpPMTHy2jBLL6xRk33qgDxFWX"
},
"enr/p2p/waku/boot": {
"boot-01.do-ams3.shards.test": "enr:-QEOuEAuAK49evunDoidpHqcmeVqZz73wt4jwHnHJlmCVBFj6EdIbZ9uH5BnCYKOEPJTns2QJKUR2XLtWyzIspPAfJF9AYJpZIJ2NIJpcISnYxMvim11bHRpYWRkcnO4YAAtNihib290LTAxLmRvLWFtczMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfAC82KGJvb3QtMDEuZG8tYW1zMy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAt60bRUEoHNuLlnsM12sU2PIQwBwfLIJ8a_ZPEY2-Rnkg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN",
"boot-01.gc-us-central1-a.shards.test": "enr:-QEguEC3wjzOk7U5rIqiX32CCD-0_J1cYYGK_YwKSah5di2NTxJUaKQ9B7NMiEQ_-YGm-Eus4SzHtxN_fXEuVaNHql9aAYJpZIJ2NIJpcIQihw1Xim11bHRpYWRkcnO4cgA2NjFib290LTAxLmdjLXVzLWNlbnRyYWwxLWEuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuZ2MtdXMtY2VudHJhbDEtYS5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAsY6oA0NFskUjopWFN9gwOZP1zZQ4rN5tVXV5CvcTOpDg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN",
"boot-01.ac-cn-hongkong-c.shards.test": "enr:-QEguEBb4rlxsdYCIZ8NcAlcjnb2zp4C9JbDsz-01Ix2sKNdWzI79KRFnhlakX-4F8gRYcviDvQL5eEZDOxHTupUW7VXAYJpZIJ2NIJpcIQI2hdMim11bHRpYWRkcnO4cgA2NjFib290LTAxLmFjLWNuLWhvbmdrb25nLWMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuYWMtY24taG9uZ2tvbmctYy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAz-wm0ZPmCicDhRTOGfZ3stBj3O1jyWgsBpKTUcpWu5gg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN"
"boot-01.do-ams3.shards.test": "enr:-QEQuEAdkU8UWa5vvRr-uoULGoyWflIOozVUWj-9iUXw7nEo_yWKmDKrYJ_t4rSwbRLobDy8M0mO8HQyDFVfdQxDZQRVAYJpZIJ2NIJpcISnYxMvim11bHRpYWRkcnO4YAAtNihib290LTAxLmRvLWFtczMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfAC82KGJvb3QtMDEuZG8tYW1zMy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEC3rRtFQSgc24uWewzXaxTY8hDAHB8sgnxr9k8Rjb5GeSDdGNwgnZfg3VkcIIjKIV3YWt1Mg0",
"boot-01.gc-us-central1-a.shards.test": "enr:-QEiuECIDOWRVQAUq2xpm3EUhuLRH1e_WCiLa6-5zmLoyVB-QSkSealvjt5Zb7cEqhU0pIeRaqnX6b8s98BahmG2XaSIAYJpZIJ2NIJpcIQihw1Xim11bHRpYWRkcnO4cgA2NjFib290LTAxLmdjLXVzLWNlbnRyYWwxLWEuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuZ2MtdXMtY2VudHJhbDEtYS5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaECxjqgDQ0WyRSOilYU32DA5k_XNlDis3m1VdXkK9xM6kODdGNwgnZfg3VkcIIjKIV3YWt1Mg0",
"boot-01.ac-cn-hongkong-c.shards.test": "enr:-QEiuEDvfBDIqKRhdBHfGkRLvbYdD8Cja_m8tqWqUG40zXDUSTWejzvi2TL7z4H9gMhy2asTJ0vBTMjpQPj6Te-e2uAFAYJpZIJ2NIJpcIQI2hdMim11bHRpYWRkcnO4cgA2NjFib290LTAxLmFjLWNuLWhvbmdrb25nLWMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuYWMtY24taG9uZ2tvbmctYy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEDP7CbRk-YKJwOFFM4Z9ney0GPc7WPJaCwGkpNRyla7mCDdGNwgnZfg3VkcIIjKIV3YWt1Mg0"
},
"wss/p2p/waku/boot": {
"boot-01.do-ams3.shards.test": "/dns4/boot-01.do-ams3.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmAR24Mbb6VuzoyUiGx42UenDkshENVDj4qnmmbabLvo31",
@@ -201,12 +184,12 @@
"store-02.ac-cn-hongkong-c.shards.test": "/dns4/store-02.ac-cn-hongkong-c.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAm9CQhsuwPR54q27kNj9iaQVfyRzTGKrhFmr94oD8ujU6P"
},
"enr/p2p/waku/store": {
"store-01.do-ams3.shards.test": "enr:-QEQuEDom7vBcLEP3ZCvRGPyBVTUJUO5YIyXvxcibag_iq6s5Ux6Zd1_nnqEXqynppYMNOTaTzSetRhmV9IH83j72umYAYJpZIJ2NIJpcISf3_Jeim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEC36GkB96EmFufcsRAX3gGW5bZlJwuAc2JB6nq9lUDE8qDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.do-ams3.shards.test": "enr:-QEQuEAmPituRLmZuwA6z0AT_Vl-KWbb7kpyX7qcWwbjygv_Oxrdu_0kmpShNtauWxhRmaOMOYddv9IwiIS8HujxHvpbAYJpZIJ2NIJpcISf3_Kaim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEC0jOth5qhqWd_NmDOAsiPjAiJZMTD-2WzsKsET75PcLCDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-01.gc-us-central1-a.shards.test": "enr:-QEiuEBW0x-NQAwfFIgwrwtMRbPpWYRbWzsQ6nMDQK5K8vT8uAph5mlAw-TaeIxw9K2Vc0QuEYzf8-MnOESVyQ-C6ywcAYJpZIJ2NIJpcIQiqsAnim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEDf2gcTbDga3Hgy8gu-bwRUbs7_7Vn2hxudCXPQ0M7cJCDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.gc-us-central1-a.shards.test": "enr:-QEiuEDjbS1EbRmNA7Gl1F3z_NsTHloyfZp4h0tm5cQmTvo5SlFGIBPPpmB6oycGnVGCHFPmqV_XbJJRO5pObWa5dOHgAYJpZIJ2NIJpcIQiqpoCim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEDWxINW5DCQgYg-U43t2f9dUfpHfZrp2RdL-IomGWtY4KDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-01.ac-cn-hongkong-c.shards.test": "enr:-QEiuEDkMIJT5pVMmtzHD5RATLyU0kAG0tKcC3AE3BQe0O6S9R6OsA7PEVaaUg52fA4_I2pwjoW2GroE6uR9a-7Vdfy-AYJpZIJ2NIJpcIQI2kpJim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaECZtdI3Wq88fYXHYUShn7AMktB3OaVo98ock70-RSMChiDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.ac-cn-hongkong-c.shards.test": "enr:-QEiuEBzOdkswwOBobEe-nUvdtALMP8sjV9b_v9rQS4E0QOv2TVdrXRKKrBzOgk8TIXFtdry3RrowN5pTH7vBWl8TPKUAYJpZIJ2NIJpcIQI2nnoim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaECzJ3LruqSdw0Ec2FKpAdT22kcWVyBiYvMGim2wRWzkjSDdGNwgnZfg3VkcIIjKIV3YWt1MgM"
"store-01.do-ams3.shards.test": "enr:-QESuEBxlk35-NNVnppRQaNSB3fR4M7J7xK3NUYer3z-L9j0uTpg9MatcSEHLUFkf4lt5qxacyBxD6G1w5elhdSgeKo4AYJpZIJ2NIJpcISf3_Jeim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQLfoaQH3oSYW59yxEBfeAZbltmUnC4BzYkHqer2VQMTyoN0Y3CCdl-DdWRwgiMohXdha3UyAw",
"store-02.do-ams3.shards.test": "enr:-QESuEC_CCKHt-bfmNcpFhY4_RyzEPfb9qXDzc7-2mo0oTanx2pMNLVkGYQuAWzgS14nGqecJ4qNGnJf0iW6xmk7bvgSAYJpZIJ2NIJpcISf3_Kaim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQLSM62HmqGpZ382YM4CyI-MCIlkxMP7ZbOwqwRPvk9wsIN0Y3CCdl-DdWRwgiMohXdha3UyAw",
"store-01.gc-us-central1-a.shards.test": "enr:-QEkuEDdeEvvLl4imez1cjafogCr4Y9TC739Io6U7J78VG6ong2UtkKNADtupsHKArUcc13jCZI_O4z6XnLz6zYLpDn-AYJpZIJ2NIJpcIQiqsAnim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQN_aBxNsOBrceDLyC75vBFRuzv_tWfaHG50Jc9DQztwkIN0Y3CCdl-DdWRwgiMohXdha3UyAw",
"store-02.gc-us-central1-a.shards.test": "enr:-QEkuEA98rxs-uF2s5E1qVW-yg7p7y6JZ5sFCDmeQOvaeQekLwbEO_O68XfOFCmuJsWwmA00HtnnbkAfFaYy0ZhsHWbKAYJpZIJ2NIJpcIQiqpoCim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQNbEg1bkMJCBiD5Tje3Z_11R-kd9munZF0v4iiYZa1jgoN0Y3CCdl-DdWRwgiMohXdha3UyAw",
"store-01.ac-cn-hongkong-c.shards.test": "enr:-QEkuEAIYrY2284THz1f4FkFEr7PIHw5GrBLEd_4UZWMh1aCGUzePYMf-YIaw_-bEqfqRK_1p7RJVgLupl8EaENIUXG3AYJpZIJ2NIJpcIQI2kpJim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQJm10jdarzx9hcdhRKGfsAyS0Hc5pWj3yhyTvT5FIwKGIN0Y3CCdl-DdWRwgiMohXdha3UyAw",
"store-02.ac-cn-hongkong-c.shards.test": "enr:-QEkuECDx1C82BBcVM4UAFnTNTRe8zwX6vIy3iYU3qOyJJZGuDhceqbwVwW_Nc5j6tAUgnotg_jiZiNXoj_tJrFildM4AYJpZIJ2NIJpcIQI2nnoim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJzjQAQBQABACAAQACAAQCJc2VjcDI1NmsxoQLMncuu6pJ3DQRzYUqkB1PbaRxZXIGJi8waKbbBFbOSNIN0Y3CCdl-DdWRwgiMohXdha3UyAw"
},
"wss/p2p/waku/store": {
"store-01.do-ams3.shards.test": "/dns4/store-01.do-ams3.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmAUdrQ3uwzuE4Gy4D56hX6uLKEeerJAnhKEHZ3DxF1EfT",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

+14 -10
View File
@@ -11,9 +11,11 @@
[legacy.status-im.utils.random :as random]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[react-native.core :as react]
[react-native.platform :as platform]
[status-im.common.json-rpc.events :as json-rpc]
[status-im.common.universal-links :as links]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.chat.events :as chat.events]
[status-im.navigation.events :as navigation]
@@ -302,16 +304,18 @@
:history [normalized-url]}]
(if (links/universal-link? normalized-url)
{:dispatch [:universal-links/handle-url normalized-url]}
(rf/merge cofx
{:db (assoc db
:browser/options
{:browser-id (:browser-id browser)}
:browser/screen-id :browser)}
(navigation/pop-to-root :shell-stack)
(chat.events/close-chat)
(navigation/change-tab :browser-stack)
(update-browser browser)
(resolve-url nil)))))
(if config/show-not-implemented-features?
(rf/merge cofx
{:db (assoc db
:browser/options
{:browser-id (:browser-id browser)}
:browser/screen-id :browser)}
(navigation/pop-to-root :shell-stack)
(chat.events/close-chat)
(navigation/change-tab :browser-stack)
(update-browser browser)
(resolve-url nil))
(.openURL ^js react/linking (url/normalize-url url))))))
(rf/defn open-existing-browser
"Opens an existing browser with it's history"
+89 -90
View File
@@ -1,8 +1,5 @@
(ns legacy.status-im.browser.core-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[legacy.status-im.browser.core :as browser]
[utils.i18n :as i18n]
[utils.url :as url]))
(defn has-wrong-properties?
@@ -21,101 +18,103 @@
(some #(when (= (url/normalize-and-decode-url dapp-url) (first (:history %))) (:browser-id %))
(vals (get-in result [:db :browser/browsers]))))
(deftest browser-test
(let [dapp1-url "cryptokitties.co"
dapp2-url "http://test2.com"]
#_(deftest browser-test
(let [dapp1-url "cryptokitties.co"
dapp2-url "http://test2.com"]
(testing "user opens a dapp"
(let [result-open (browser/open-url {:db {} :now 1} dapp1-url)
dapp1-id (get-dapp-id result-open dapp1-url)]
(is (= dapp1-id (get-in result-open [:db :browser/options :browser-id]))
"browser-id should be dapp1-url")
(is (not (has-wrong-properties? result-open
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co"]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(testing "user opens a dapp"
(let [result-open (browser/open-url {:db {} :now 1} dapp1-url)
dapp1-id (get-dapp-id result-open dapp1-url)]
(is (= dapp1-id (get-in result-open [:db :browser/options :browser-id]))
"browser-id should be dapp1-url")
(is (not (has-wrong-properties? result-open
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co"]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(testing "then a second dapp"
(let [result-open-2 (browser/open-url {:db (:db result-open)
:now 2}
dapp2-url)
dapp2-id (get-dapp-id result-open-2 dapp2-url)]
(is (= dapp2-id (get-in result-open-2 [:db :browser/options :browser-id]))
"browser-id should be dapp2 host")
(is (not (has-wrong-properties? result-open-2
dapp2-id
{:browser-id dapp2-id
:history-index 0
:history ["http://test2.com"]
:dapp? false}))
"some properties of the browser are not correct")
(testing "then a second dapp"
(let [result-open-2 (browser/open-url {:db (:db result-open)
:now 2}
dapp2-url)
dapp2-id (get-dapp-id result-open-2 dapp2-url)]
(is (= dapp2-id (get-in result-open-2 [:db :browser/options :browser-id]))
"browser-id should be dapp2 host")
(is (not (has-wrong-properties? result-open-2
dapp2-id
{:browser-id dapp2-id
:history-index 0
:history ["http://test2.com"]
:dapp? false}))
"some properties of the browser are not correct")
(testing "then removes the second dapp"
(let [result-remove-2 (browser/remove-browser {:db (:db result-open-2)} dapp2-id)]
(is (= #{dapp1-id}
(set (keys (get-in result-remove-2 [:db :browser/browsers]))))
"the second dapp shouldn't be in the browser list anymore")))))
(testing "then removes the second dapp"
(let [result-remove-2 (browser/remove-browser {:db (:db result-open-2)} dapp2-id)]
(is (= #{dapp1-id}
(set (keys (get-in result-remove-2 [:db :browser/browsers]))))
"the second dapp shouldn't be in the browser list anymore")))))
(testing "then opens the dapp again"
(let [result-open-existing (browser/open-existing-browser {:db (:db result-open)
:now 2}
dapp1-id)
dapp1-url2 (str "https://" dapp1-url "/nav2")]
(is (not (has-wrong-properties? result-open-existing
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co"]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(is (nil? (browser/navigate-to-next-page result-open-existing))
"nothing should happen if user tries to navigate to next page")
(is (nil? (browser/navigate-to-previous-page result-open-existing))
"nothing should happen if user tries to navigate to previous page")
(testing "then opens the dapp again"
(let [result-open-existing (browser/open-existing-browser {:db (:db result-open)
:now 2}
dapp1-id)
dapp1-url2 (str "https://" dapp1-url "/nav2")]
(is (not (has-wrong-properties? result-open-existing
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co"]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(is (nil? (browser/navigate-to-next-page result-open-existing))
"nothing should happen if user tries to navigate to next page")
(is (nil? (browser/navigate-to-previous-page result-open-existing))
"nothing should happen if user tries to navigate to previous page")
(testing "then navigates to a new url in the dapp"
(let [result-navigate (browser/navigation-state-changed
{:db (:db result-open-existing)
:now 4}
(clj->js {"url" dapp1-url2
"loading" false})
false)]
(is (not (has-wrong-properties? result-navigate
dapp1-id
{:browser-id dapp1-id
:history-index 1
:history ["https://cryptokitties.co" dapp1-url2]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(testing "then navigates to previous page"
(let [result-previous (browser/navigate-to-previous-page {:db (:db result-navigate)
:now 5})]
(is
(not (has-wrong-properties? result-previous
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co" dapp1-url2]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(testing "then navigates to next page")
(let [result-next (browser/navigate-to-next-page {:db (:db result-previous)
:now 6})]
(is (not
(has-wrong-properties? result-next
(testing "then navigates to a new url in the dapp"
(let [result-navigate (browser/navigation-state-changed
{:db (:db result-open-existing)
:now 4}
(clj->js {"url" dapp1-url2
"loading" false})
false)]
(is (not (has-wrong-properties? result-navigate
dapp1-id
{:browser-id dapp1-id
:history-index 1
:history ["https://cryptokitties.co" dapp1-url2]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct"))))))))))))
"some properties of the browser are not correct")
(testing "then navigates to previous page"
(let [result-previous (browser/navigate-to-previous-page {:db (:db result-navigate)
:now 5})]
(is
(not (has-wrong-properties? result-previous
dapp1-id
{:browser-id dapp1-id
:history-index 0
:history ["https://cryptokitties.co"
dapp1-url2]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct")
(testing "then navigates to next page")
(let [result-next (browser/navigate-to-next-page {:db (:db result-previous)
:now 6})]
(is (not
(has-wrong-properties? result-next
dapp1-id
{:browser-id dapp1-id
:history-index 1
:history ["https://cryptokitties.co"
dapp1-url2]
:dapp? false
:name (i18n/label :t/browser)}))
"some properties of the browser are not correct"))))))))))))
@@ -1,96 +1,90 @@
(ns legacy.status-im.browser.permissions-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[legacy.status-im.browser.core :as browser]
[legacy.status-im.browser.core-test :as core.tests]
[legacy.status-im.browser.permissions :as permissions]
[legacy.status-im.utils.deprecated-types :as types]))
(ns legacy.status-im.browser.permissions-test)
(deftest permissions-test
(let [dapp-name "test.com"
dapp-name2 "test2.org"
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
[:profile/profile :public-key]
"public-key")}
dapp-id (core.tests/get-dapp-id cofx dapp-name)]
(testing "dapps permissions are initialized"
(is (zero? (count (get-in cofx [:db :dapps/permissions]))))
(is (= dapp-id (get-in cofx [:db :browser/options :browser-id]))))
#_(deftest permissions-test
(let [dapp-name "test.com"
dapp-name2 "test2.org"
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
[:profile/profile :public-key]
"public-key")}
dapp-id (core.tests/get-dapp-id cofx dapp-name)]
(testing "dapps permissions are initialized"
(is (zero? (count (get-in cofx [:db :dapps/permissions]))))
(is (= dapp-id (get-in cofx [:db :browser/options :browser-id]))))
(testing "receiving an unsupported permission"
(let [result-ask (browser/process-bridge-message cofx
(types/clj->json
{:type "api-request"
:host dapp-name
:messageId 0
:permission "FAKE_PERMISSION"}))]
(is (not (get-in result-ask [:browser/send-to-bridge :isAllowed])))))
(testing "receiving an unsupported permission"
(let [result-ask (browser/process-bridge-message cofx
(types/clj->json
{:type "api-request"
:host dapp-name
:messageId 0
:permission "FAKE_PERMISSION"}))]
(is (not (get-in result-ask [:browser/send-to-bridge :isAllowed])))))
(testing "receiving a supported permission"
(let [result-ask (browser/process-bridge-message cofx
(types/clj->json {:type "api-request"
(testing "receiving a supported permission"
(let [result-ask (browser/process-bridge-message cofx
(types/clj->json {:type "api-request"
:host dapp-name
:messageId 1
:permission "contact-code"}))]
(is (= (get-in result-ask [:db :browser/options :show-permission])
{:requested-permission "contact-code"
:dapp-name "test.com"
:message-id 1
:yield-control? nil}))
(is (zero? (count (get-in result-ask [:db :dapps/permissions]))))
(testing "then user accepts the supported permission"
(let [accept-result (permissions/allow-permission {:db (:db result-ask)})]
(is (= (get accept-result :browser/send-to-bridge)
{:type "api-response"
:messageId 1
:isAllowed true
:data "public-key"
:permission "contact-code"})
"the data should have been sent to the bridge")
(is (= (get-in accept-result [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}})
"the dapp should now have CONTACT_CODE permission")
(testing "then dapp asks for permission again"
(let [result-ask-again (browser/process-bridge-message {:db (:db accept-result)}
(types/clj->json
{:type "api-request"
:host dapp-name
:messageId 1
:messageId 2
:permission "contact-code"}))]
(is (= (get-in result-ask [:db :browser/options :show-permission])
{:requested-permission "contact-code"
:dapp-name "test.com"
:message-id 1
:yield-control? nil}))
(is (zero? (count (get-in result-ask [:db :dapps/permissions]))))
(is (= (get result-ask-again :browser/send-to-bridge)
{:type "api-response"
:isAllowed true
:messageId 2
:data "public-key"
:permission "contact-code"})
"the response should be immediatly sent to the bridge")))
(testing "then user accepts the supported permission"
(let [accept-result (permissions/allow-permission {:db (:db result-ask)})]
(is (= (get accept-result :browser/send-to-bridge)
{:type "api-response"
:messageId 1
:isAllowed true
:data "public-key"
:permission "contact-code"})
"the data should have been sent to the bridge")
(is (= (get-in accept-result [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}})
"the dapp should now have CONTACT_CODE permission")
(testing "then user switch to another dapp that asks for permissions"
(let [new-dapp (browser/open-url {:db (:db accept-result)} dapp-name2)
result-ask2 (browser/process-bridge-message {:db (:db new-dapp)}
(types/clj->json
{:type "api-request"
:host dapp-name2
:messageId 3
:permission "contact-code"}))]
(is (= (get-in result-ask2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}})
"there should only be permissions for dapp-name at that point")
(is (nil? (get result-ask2 :browser/send-to-bridge))
"no message should be sent to the bridge")
(testing "then dapp asks for permission again"
(let [result-ask-again (browser/process-bridge-message {:db (:db accept-result)}
(types/clj->json
{:type "api-request"
:host dapp-name
:messageId 2
:permission "contact-code"}))]
(is (= (get result-ask-again :browser/send-to-bridge)
{:type "api-response"
:isAllowed true
:messageId 2
:data "public-key"
:permission "contact-code"})
"the response should be immediatly sent to the bridge")))
(testing "then user switch to another dapp that asks for permissions"
(let [new-dapp (browser/open-url {:db (:db accept-result)} dapp-name2)
result-ask2 (browser/process-bridge-message {:db (:db new-dapp)}
(types/clj->json
{:type "api-request"
:host dapp-name2
:messageId 3
:permission "contact-code"}))]
(is (= (get-in result-ask2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}})
"there should only be permissions for dapp-name at that point")
(is (nil? (get result-ask2 :browser/send-to-bridge))
"no message should be sent to the bridge")
(testing "then user accepts permission for dapp-name2"
(let [accept-result2 (permissions/allow-permission {:db (:db result-ask2)})]
(is (= (get-in accept-result2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}
"test2.org" {:dapp "test2.org" :permissions ["contact-code"]}})
"there should be permissions for both dapps now")
(is (= (get accept-result2 :browser/send-to-bridge)
{:type "api-response"
:isAllowed true
:messageId 3
:data "public-key"
:permission "contact-code"})
"the response should be sent to the bridge")))))))))))
(testing "then user accepts permission for dapp-name2"
(let [accept-result2 (permissions/allow-permission {:db (:db result-ask2)})]
(is (= (get-in accept-result2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}
"test2.org" {:dapp "test2.org" :permissions ["contact-code"]}})
"there should be permissions for both dapps now")
(is (= (get accept-result2 :browser/send-to-bridge)
{:type "api-response"
:isAllowed true
:messageId 3
:data "public-key"
:permission "contact-code"})
"the response should be sent to the bridge")))))))))))
+1 -2
View File
@@ -9,8 +9,7 @@
(testing "it returns the default fleets"
(is (=
#{:eth.prod
:eth.staging
:eth.test}
:eth.staging}
(into #{}
(keys (node/fleets {})))))))
(testing "passing a custom fleet"
@@ -5,6 +5,7 @@
[legacy.status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.config :as config]
[utils.i18n :as i18n]
[utils.url :as url]))
@@ -27,10 +28,13 @@
(defn browse
[link]
(show {:title (i18n/label :t/browsing-title)
:options [{:label (i18n/label :t/browsing-open-in-status)
:action #(re-frame/dispatch [:browser.ui/open-url link])}
{:label (i18n/label (platform-web-browser))
:action #(.openURL ^js react/linking (url/normalize-url link))}]
:options (if config/show-not-implemented-features?
[{:label (i18n/label :t/browsing-open-in-status)
:action #(re-frame/dispatch [:browser.ui/open-url link])}
{:label (i18n/label (platform-web-browser))
:action #(.openURL ^js react/linking (url/normalize-url link))}]
[{:label (i18n/label (platform-web-browser))
:action #(.openURL ^js react/linking (url/normalize-url link))}])
:cancel-text (i18n/label :t/browsing-cancel)}))
(defn browse-in-web-browser
@@ -10,12 +10,13 @@
:image - collection image
:theme - keyword -> :light/:dark"
[{:keys [image size on-load-end on-error] :or {size :size-24}}]
[{:keys [image size on-load-start on-load-end on-error] :or {size :size-24}}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (style/collection-avatar-container theme size)}
[fast-image/fast-image
{:accessibility-label :collection-avatar
:source image
:on-load-start on-load-start
:on-load-end on-load-end
:on-error on-error
:style (style/collection-avatar size)}]]))
@@ -0,0 +1,9 @@
(ns quo.components.avatars.community-avatar.component-spec
(:require [quo.components.avatars.community-avatar.view :as community-avatar]
[test-helpers.component :as h]))
(h/describe "Avatars: Community Avatar"
(h/test "should render correctly"
(h/render-with-theme-provider
[community-avatar/view {:image "mock-image"}])
(h/is-truthy (h/get-by-label-text :community-avatar))))
@@ -0,0 +1,12 @@
(ns quo.components.avatars.community-avatar.style)
(def ^:private sizes
{:size-32 32
:size-24 24})
(defn image
[size]
(let [size-val (sizes size)]
{:border-radius (/ size-val 2)
:width size-val
:height size-val}))
@@ -0,0 +1,23 @@
(ns quo.components.avatars.community-avatar.view
(:require [quo.components.avatars.community-avatar.style :as style]
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:size {:optional true} [:maybe [:enum :size-32 :size-24]]]
[:image :schema.common/image-source]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [size image container-style]}]
[rn/image
{:source image
:accessibility-label :community-avatar
:style (merge (style/image size) container-style)}])
(def view (schema/instrument #'view-internal ?schema))
@@ -0,0 +1,14 @@
(ns quo.components.avatars.dapp-avatar.component-spec
(:require [quo.components.avatars.dapp-avatar.view :as dapp-avatar]
[test-helpers.component :as h]))
(h/describe "Avatars: dApp Avatar"
(h/test "should render correctly without context"
(h/render-with-theme-provider
[dapp-avatar/view {:image "mock-image"}])
(h/is-truthy (h/get-by-label-text :dapp-avatar)))
(h/test "should render correctly with context"
(h/render-with-theme-provider
[dapp-avatar/view {:image "mock-image" :network-image "mock-image" :context? true}])
(h/is-truthy (h/get-by-label-text :dapp-avatar))))
@@ -0,0 +1,23 @@
(ns quo.components.avatars.dapp-avatar.style)
(def ^:const size 32)
(def container
{:height size
:width size})
(def hole-view
{:width size
:height size})
(def context
{:width 16
:height 16
:border-radius 8
:position :absolute
:right -4
:bottom -4})
(def image
{:width size
:height size})
@@ -0,0 +1,42 @@
(ns quo.components.avatars.dapp-avatar.view
(:require [quo.components.avatars.dapp-avatar.style :as style]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:context? {:optional true} [:maybe :boolean]]
[:image :schema.common/image-source]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [context? image network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :dapp-avatar}
[hole-view/hole-view
(cond-> {:holes (if context?
[{:x 19
:y 19
:width 18
:height 18
:borderRadius 9}]
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[rn/image
{:source image
:style style/image}]]
(when context?
[rn/image
{:source network-image
:style style/context}])])
(def view (schema/instrument #'view-internal ?schema))
@@ -0,0 +1,14 @@
(ns quo.components.avatars.token-avatar.component-spec
(:require [quo.components.avatars.token-avatar.view :as token-avatar]
[test-helpers.component :as h]))
(h/describe "Avatars: Token Avatar"
(h/test "should render correctly without context"
(h/render-with-theme-provider
[token-avatar/view {:image "mock-image"}])
(h/is-truthy (h/get-by-label-text :token-avatar)))
(h/test "should render correctly with context"
(h/render-with-theme-provider
[token-avatar/view {:image "mock-image" :network-image "mock-image" :context? true}])
(h/is-truthy (h/get-by-label-text :token-avatar))))
@@ -0,0 +1,25 @@
(ns quo.components.avatars.token-avatar.style)
(def ^:const size 32)
(def container
{:height size
:width size})
(def hole-view
{:width size
:height size})
(def context
{:width 16
:height 16
:border-radius 8
:position :absolute
:right -4
:bottom -4})
(defn image
[type]
{:width size
:border-radius (if (= type :collectible) 8 0)
:height size})
@@ -0,0 +1,43 @@
(ns quo.components.avatars.token-avatar.view
(:require [quo.components.avatars.token-avatar.style :as style]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type {:optional true} [:enum :asset :collectible]]
[:context? {:optional true} [:maybe :boolean]]
[:image :schema.common/image-source]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [type context? image network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :token-avatar}
[hole-view/hole-view
(cond-> {:holes (if context?
[{:x 19
:y 19
:width 18
:height 18
:borderRadius 9}]
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[rn/image
{:source image
:style (style/image type)}]]
(when context?
[rn/image
{:source network-image
:style style/context}])])
(def view (schema/instrument #'view-internal ?schema))
+1 -3
View File
@@ -35,7 +35,6 @@
size 40
customization-color (if (= type :primary) :blue nil)}}
children]
(when (string? children) (js/console.log "button - " children))
(let [[pressed-state? set-pressed-state] (rn/use-state false)
theme (quo.theme/use-theme)
{:keys [icon-color background-color label-color border-color blur-type
@@ -118,8 +117,7 @@
{:size (when (#{56 24} size) :paragraph-2)
:weight :medium
:number-of-lines 1
:style {:color label-color
:opacity (when disabled? 0.3)}}
:style {:color label-color}}
children]
(vector? children)
@@ -0,0 +1,23 @@
(ns quo.components.buttons.swap-order-button.component-spec
(:require [quo.components.buttons.swap-order-button.view :as swap-order-button]
[test-helpers.component :as h]))
(h/describe "Buttons: Swap Order Button"
(h/test "should render correctly"
(h/render-with-theme-provider
[swap-order-button/view {:on-press identity}])
(h/is-truthy (h/get-by-label-text :swap-order-button)))
(h/test "should call on-press handler when pressed"
(let [on-press (h/mock-fn)]
(h/render-with-theme-provider
[swap-order-button/view {:on-press on-press}])
(h/fire-event :press (h/get-by-label-text :swap-order-button))
(h/was-called on-press)))
(h/test "should not call on-press handler when button is disabled"
(let [on-press (h/mock-fn)]
(h/render-with-theme-provider
[swap-order-button/view {:on-press on-press :disabled? true}])
(h/fire-event :press (h/get-by-label-text :swap-order-button))
(h/was-not-called on-press))))
@@ -0,0 +1,11 @@
(ns quo.components.buttons.swap-order-button.schema)
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:disabled? {:optional true} [:maybe :boolean]]
[:on-press fn?]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
@@ -0,0 +1,18 @@
(ns quo.components.buttons.swap-order-button.style
(:require [quo.foundations.colors :as colors]))
(defn container
[pressed? disabled? theme]
{:width 32
:height 32
:border-radius 10
:border-width 1
:opacity (if disabled? 0.3 1)
:align-items :center
:justify-content :center
:border-color (if pressed?
(colors/theme-colors colors/neutral-20 colors/neutral-60 theme)
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))
:background-color (if pressed?
(colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
(colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme))})
@@ -0,0 +1,28 @@
(ns quo.components.buttons.swap-order-button.view
(:require [quo.components.buttons.swap-order-button.schema :as swap-order-button.schema]
[quo.components.buttons.swap-order-button.style :as style]
[quo.components.icon :as icon]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(defn- view-internal
[{:keys [disabled? on-press container-style]}]
(let [theme (quo.theme/use-theme)
[pressed? set-pressed] (rn/use-state false)
on-press-in (rn/use-callback #(set-pressed true) [])
on-press-out (rn/use-callback #(set-pressed false) [])]
[rn/pressable
{:style (merge (style/container pressed? disabled? theme)
container-style)
:accessibility-label :swap-order-button
:disabled disabled?
:on-press on-press
:on-press-in on-press-in
:on-press-out on-press-out}
[icon/icon :i/arrow-down
{:size 20
:color (colors/theme-colors colors/neutral-100 colors/white theme)}]]))
(def view (schema/instrument #'view-internal swap-order-button.schema/?schema))
@@ -80,10 +80,10 @@
(h/is-truthy (h/get-by-text "0x62b...0a5"))
(h/is-truthy (h/get-by-label-text :account-avatar)))
(h/test "component renders in keypair type when keycard? is false"
(h/test "component renders keypair type with default label"
(h/render-with-theme-provider [quo/drawer-top
{:title "Title"
:keycard? false
:stored nil
:icon-avatar :i/placeholder
:type :keypair}]
theme)
@@ -91,10 +91,21 @@
(-> (h/expect (h/get-by-translation-text :t/on-device))
(.toBeTruthy)))
(h/test "component renders in keypair type when keycard? is true"
(h/test "component renders keypair type when stored on device"
(h/render-with-theme-provider [quo/drawer-top
{:title "Title"
:keycard? true
:stored :on-device
:icon-avatar :i/placeholder
:type :keypair}]
theme)
(h/is-truthy (h/get-by-text "Title"))
(-> (h/expect (h/get-by-translation-text :t/on-device))
(.toBeTruthy)))
(h/test "component renders keypair type when stored on keycard"
(h/render-with-theme-provider [quo/drawer-top
{:title "Title"
:stored :on-keycard
:icon-avatar :i/placeholder
:type :keypair}]
theme)
@@ -102,6 +113,17 @@
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
(.toBeTruthy)))
(h/test "component renders keypair type when considered missing"
(h/render-with-theme-provider [quo/drawer-top
{:title "Title"
:stored :missing
:icon-avatar :i/placeholder
:type :keypair}]
theme)
(h/is-truthy (h/get-by-text "Title"))
(-> (h/expect (h/get-by-translation-text :t/import-to-use-derived-accounts))
(.toBeTruthy)))
(h/test "component renders in default-keypair type"
(h/render-with-theme-provider [quo/drawer-top
{:title "Title"
+12 -10
View File
@@ -37,16 +37,18 @@
nil))
(defn- keypair-subtitle
[{:keys [theme blur? keycard?]}]
[{:keys [theme blur? stored]}]
[rn/view {:style style/row}
[text/text
{:size :paragraph-2
:weight :regular
:style (style/description theme blur?)}
(if keycard?
(i18n/label :t/on-keycard)
(case stored
:on-device (i18n/label :t/on-device)
:on-keycard (i18n/label :t/on-keycard)
:missing (i18n/label :t/import-to-use-derived-accounts)
(i18n/label :t/on-device))]
(when keycard?
(when (= stored :on-keycard)
[icons/icon
:i/keycard-card
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
@@ -103,14 +105,14 @@
description])
(defn- subtitle
[{:keys [type theme blur? keycard? networks description community-name community-logo
[{:keys [type theme blur? stored networks description community-name community-logo
context-tag-type account-name emoji customization-color full-name profile-picture]}]
(cond
(= :keypair type)
[keypair-subtitle
{:theme theme
:blur? blur?
:keycard? keycard?}]
{:theme theme
:blur? blur?
:stored stored}]
(= :account type)
[account-subtitle
@@ -195,7 +197,7 @@
(defn view
[{:keys [title title-icon type description blur? community-name community-logo button-icon
account-name emoji context-tag-type button-type container-style
on-button-press on-button-long-press profile-picture keycard? networks label full-name
on-button-press on-button-long-press profile-picture stored networks label full-name
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar]}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (merge style/container container-style)}
@@ -220,7 +222,7 @@
{:type type
:theme theme
:blur? blur?
:keycard? keycard?
:stored stored
:networks networks
:description description
:community-name community-name
@@ -0,0 +1,30 @@
(ns quo.components.list-items.missing-keypair.component-spec
(:require
[quo.components.list-items.missing-keypair.view :as missing-keypair]
[test-helpers.component :as h]))
(def keypair-data
{:accounts []
:name "Key Pair Name"})
(def props
{:keypair keypair-data
:blur? true
:on-options-press (fn [])})
(h/describe "List items: missing keypair item"
(h/test "Test item container renders"
(h/render-with-theme-provider [missing-keypair/view props])
(h/is-truthy (h/get-by-label-text :missing-keypair-item)))
(h/test "Test keypair icon renders"
(h/render-with-theme-provider [missing-keypair/view props])
(h/is-truthy (h/get-by-label-text :icon)))
(h/test "Test name renders"
(h/render-with-theme-provider [missing-keypair/view props])
(h/is-truthy (h/get-by-label-text :name)))
(h/test "Test preview-list renders"
(h/render-with-theme-provider [missing-keypair/view props])
(h/is-truthy (h/get-by-label-text :preview-list)))
(h/test "Test options button renders"
(h/render-with-theme-provider [missing-keypair/view props])
(h/is-truthy (h/get-by-label-text :options-button))))
@@ -0,0 +1,25 @@
(ns quo.components.list-items.missing-keypair.schema)
(def ^:private ?base
[:map
[:blur? {:optional true} [:maybe :boolean]]
[:keypair
[:map
[:key-uid :string]
[:name :string]
[:accounts
[:sequential
[:map {:closed true}
[:type [:enum :default]]
[:emoji :string]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]]]])
(def ^:private ?on-option-press
[:map
[:on-options-press {:optional true} [:maybe fn?]]])
(def ?schema
[:=>
[:cat
[:merge ?base ?on-option-press]]
:any])
@@ -0,0 +1,46 @@
(ns quo.components.list-items.missing-keypair.style
(:require
[quo.foundations.colors :as colors]))
(defn container
[{:keys [blur? theme]}]
{:flex-direction :row
:align-items :center
:flex 1
:padding-right 12
:padding-left 8
:padding-vertical 8
:border-radius 12
:border-width (if blur? 0 1)
:border-color (colors/theme-colors colors/neutral-10
colors/neutral-80
theme)
:background-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-2_5
colors/neutral-80-opa-40
theme))})
(defn icon-container
[{:keys [blur? theme]}]
{:border-radius 32
:border-width 1
:border-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-20
colors/neutral-80
theme))})
(def name-container
{:flex 1
:padding-right 16
:padding-left 8})
(def preview-list-container
{:padding-right 16})
(defn options-icon-color
[{:keys [theme blur?]}]
(if blur?
colors/white-opa-70
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
@@ -0,0 +1,56 @@
(ns quo.components.list-items.missing-keypair.view
(:require
[quo.components.avatars.icon-avatar :as icon-avatar]
[quo.components.icon :as icon]
[quo.components.list-items.missing-keypair.schema :as component-schema]
[quo.components.list-items.missing-keypair.style :as style]
[quo.components.list-items.preview-list.view :as preview-list]
[quo.components.markdown.text :as text]
[quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
(defn- internal-view
[{{:keys [accounts name]} :keypair
:keys [keypair blur? on-options-press]}]
(let [theme (quo.theme/use-theme)
on-keypair-options-press (rn/use-callback
(fn [event]
(on-options-press event keypair))
[keypair on-options-press])]
[rn/view
{:style (style/container {:theme theme
:blur? blur?})
:accessibility-label :missing-keypair-item}
[rn/view
{:style (style/icon-container {:theme theme
:blur? blur?})
:accessibility-label :icon}
[icon-avatar/icon-avatar
{:size :size-32
:icon :i/seed
:color :neutral
:border? false}]]
[rn/view
{:style style/name-container
:accessibility-label :name}
[text/text
{:weight :semi-bold}
name]]
[rn/view
{:accessibility-label :preview-list}
[preview-list/view
{:blur? blur?
:type :accounts
:size :size-24
:number (count accounts)
:container-style style/preview-list-container}
accounts]]
[rn/pressable {:on-press on-keypair-options-press}
[icon/icon :i/options
{:color (style/options-icon-color
{:theme theme
:blur? blur?})
:accessibility-label :options-button}]]]))
(def view (schema/instrument #'internal-view component-schema/?schema))
@@ -8,8 +8,7 @@
(h/render-with-theme-provider component :light))
(def props
{:theme :light
:state :default
{:state :default
:label "Mainnet"
:network-image 873
:customization-color :blue
@@ -40,7 +40,6 @@
[:catn
[:props
[:map {:closed true}
[:theme :schema.common/theme]
[:network-image :int]
[:label :string]
[:fiat-value :string]
@@ -5,18 +5,22 @@
(def container-border-radius 12)
(def card-image-padding-vertical 3)
(def card-image-padding-horizontal 3)
(def default-opacity-for-loader 1)
(def default-opacity-for-image 0)
(defn fallback
[{:keys [theme]}]
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius container-border-radius
:width "100%"
:aspect-ratio 1
:align-items :center
:justify-content :center})
[{:keys [theme opacity]}]
[{:opacity opacity}
{:opacity default-opacity-for-image
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius container-border-radius
:width "100%"
:aspect-ratio 1
:align-items :center
:justify-content :center}])
(def collectible-counter
{:position :absolute
@@ -59,6 +63,15 @@
(def card-detail-text
{:flex 1})
(defn card-loader
[opacity]
[{:opacity opacity}
{:position :absolute
:opacity default-opacity-for-loader
:left 8
:align-items :center
:flex-direction :row}])
(def image-view-container
{:aspect-ratio 1
:border-radius container-border-radius})
@@ -83,6 +96,7 @@
(defn loading-image
[theme]
{:position :absolute
:opacity default-opacity-for-loader
:top 0
:bottom 0
:left 0
@@ -91,8 +105,20 @@
:background-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme)
:z-index 2})
(defn loading-image-with-opacity
[theme opacity]
[{:opacity opacity}
(loading-image theme)])
(defn avatar-container
[loaded?]
{:flex 1
:flex-direction :row
:opacity (when-not loaded? 0)})
[opacity]
[{:opacity opacity}
{:flex 1
:flex-direction :row
:opacity default-opacity-for-image}])
(defn supported-file
[opacity]
[{:opacity opacity}
{:aspect-ratio 1
:opacity default-opacity-for-image}])
@@ -10,13 +10,54 @@
[quo.foundations.gradients :as gradients]
[quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[schema.core :as schema]
[utils.datetime :as datetime]
[utils.i18n :as i18n]))
(def timing-options-out 650)
(def timing-options-in 1000)
(def first-load-time 500)
(def cached-load-time 200)
(def error-wait-time 800)
(defn on-load-end
[{:keys [load-time set-state loader-opacity image-opacity]}]
(reanimated/animate loader-opacity 0 timing-options-out)
(reanimated/animate image-opacity 1 timing-options-in)
(if (> load-time cached-load-time)
(js/setTimeout
(fn []
(set-state (fn [prev-state]
(assoc prev-state :image-loaded? true))))
first-load-time)
(set-state (fn [prev-state]
(assoc prev-state :image-loaded? true)))))
(defn on-load-error
[set-state]
(js/setTimeout (fn []
(set-state (fn [prev-state] (assoc prev-state :image-error? true))))
error-wait-time))
(defn on-load-avatar
[{:keys [load-time set-state loader-opacity avatar-opacity]}]
(reanimated/animate loader-opacity 0 timing-options-out)
(reanimated/animate avatar-opacity 1 timing-options-in)
(if (> load-time cached-load-time)
(js/setTimeout
(fn []
(set-state (fn [prev-state]
(assoc prev-state :avatar-loaded? true))))
first-load-time)
(set-state (fn [prev-state]
(assoc prev-state :avatar-loaded? true)))))
(defn- fallback-view
[{:keys [label theme]}]
[rn/view
{:style (style/fallback {:theme theme})}
[{:keys [label theme image-opacity]}]
[reanimated/view
{:style (style/fallback {:opacity image-opacity
:theme theme})}
[rn/view
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
[rn/view {:style {:height 4}}]
@@ -34,77 +75,85 @@
[rn/view {:style (style/loading-message theme)}])
(defn- loading-image
[{:keys [theme gradient-color-index]}]
[gradients/view
{:theme theme
:container-style (style/loading-image theme)
:color-index gradient-color-index}])
[{:keys [theme gradient-color-index loader-opacity]}]
[reanimated/view
{:style (style/loading-image-with-opacity theme loader-opacity)}
[gradients/view
{:theme theme
:container-style (style/loading-image theme)
:color-index gradient-color-index}]])
(defn- card-details
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
[rn/view {:style style/card-details-container}
(cond (not (:avatar-loaded? state))
[rn/view {:style {:flex-direction :row}}
[loading-square theme]
[loading-message theme]]
community?
[:<>
[preview-list/view
{:type :communities
:size :size-20}
[avatar-image-src]]
[rn/view {:style {:width 8}}]
[text/text
{:size :paragraph-1
:weight :semi-bold
:style style/card-detail-text}
collectible-name]])
[rn/view
{:style (style/avatar-container (:avatar-loaded? state))}
[:<>
[collection-avatar/view
{:size :size-20
:on-load-end #(set-state (fn [prev-state] (assoc prev-state :avatar-loaded? true)))
:image avatar-image-src}]
[rn/view {:style {:width 8}}]]
[text/text
{:size :paragraph-1
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:style style/card-detail-text}
collectible-name]]])
(let [loader-opacity (reanimated/use-shared-value 1)
avatar-opacity (reanimated/use-shared-value 0)
[load-time set-load-time] (rn/use-state (datetime/now))]
[rn/view {:style style/card-details-container}
[reanimated/view {:style (style/avatar-container avatar-opacity)}
(if community?
[preview-list/view
{:type :communities
:size :size-20}
[avatar-image-src]]
[collection-avatar/view
{:size :size-20
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-avatar {:set-state set-state
:load-time load-time
:loader-opacity loader-opacity
:avatar-opacity avatar-opacity})
:image avatar-image-src}])
[rn/view {:style {:width 8}}]
[text/text
{:size :paragraph-1
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:style style/card-detail-text}
collectible-name]]
(when (not (:avatar-loaded? state))
[reanimated/view {:style (style/card-loader loader-opacity)}
[loading-square theme]
[loading-message theme]])]))
(defn- card-view
[{:keys [avatar-image-src collectible-name community? counter state set-state
gradient-color-index image-src supported-file?]}]
(let [theme (quo.theme/use-theme)]
(let [theme (quo.theme/use-theme)
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
[load-time set-load-time] (rn/use-state (datetime/now))]
[rn/view {:style (style/card-view-container theme)}
[rn/view {:style {:aspect-ratio 1}}
(cond
(:image-error? state)
[fallback-view
{:theme theme
:label (i18n/label :t/cant-fetch-info)}]
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(not supported-file?)
[fallback-view
{:theme theme
:label (i18n/label :t/unsupported-file)}]
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state))
[loading-image
{:theme theme
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(when supported-file?
[rn/view {:style {:aspect-ratio 1}}
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load-end #(set-state (fn [prev-state] (assoc prev-state :image-loaded? true)))
:on-error #(set-state (fn [prev-state] (assoc prev-state :image-error? true)))
:source image-src}]])]
{:style style/image
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-error #(on-load-error set-state)
:source image-src}]])]
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
[collectible-counter/view
{:container-style style/collectible-counter
@@ -121,30 +170,40 @@
(defn- image-view
[{:keys [avatar-image-src community? counter state set-state
gradient-color-index image-src supported-file?]}]
(let [theme (quo.theme/use-theme)]
(let [theme (quo.theme/use-theme)
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
[load-time set-load-time] (rn/use-state (datetime/now))]
[rn/view {:style style/image-view-container}
(cond
(:image-error? state)
[fallback-view
{:theme theme
:label (i18n/label :t/cant-fetch-info)}]
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(not supported-file?)
[fallback-view
{:theme theme
:label (i18n/label :t/unsupported-file)}]
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state))
[loading-image
{:theme theme
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(when supported-file?
[rn/view {:style {:aspect-ratio 1}}
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load-end #(set-state (fn [prev-state] (assoc prev-state :image-loaded? true)))
:on-error #(set-state (fn [prev-state] (assoc prev-state :image-error? true)))
:source image-src}]])
{:style style/image
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-error #(on-load-error set-state)
:source image-src}]])
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
[collectible-counter/view
{:container-style style/collectible-counter
@@ -3,7 +3,6 @@
(def container
{:flex-direction :row
:flex 1
:justify-content :space-between})
(def right-counter
@@ -55,8 +55,8 @@
:icon-color (style/right-tag-icon-color blur? theme)}]))
(defn view
[{:keys [title right accessibility-label] :as props}]
[rn/view {:style style/container}
[{:keys [title right accessibility-label container-style] :as props}]
[rn/view {:style (merge style/container container-style)}
[text/text
{:size :heading-1
:weight :semi-bold
@@ -0,0 +1,43 @@
(ns quo.components.wallet.approval-label.component-spec
(:require [quo.components.wallet.approval-label.view :as approval-label]
[test-helpers.component :as h]))
(h/describe "Wallet: Approval Label"
(h/test "with :approve status"
(h/render-with-theme-provider
[approval-label/view
{:status :approve
:customization-color :blue
:token-value "100"
:token-symbol "SNT"}])
(h/is-truthy (h/get-by-translation-text :t/approve-amount-symbol {:amount "100" :symbol "SNT"})))
(h/test "with :approving status"
(h/render-with-theme-provider
[approval-label/view
{:status :approving
:customization-color :blue
:token-value "50"
:token-symbol "DAI"}])
(h/is-truthy (h/get-by-translation-text :t/approving-amount-symbol {:amount "50" :symbol "DAI"})))
(h/test "with :approved status"
(h/render-with-theme-provider
[approval-label/view
{:status :approved
:customization-color :blue
:token-value "5"
:token-symbol "ETH"}])
(h/is-truthy (h/get-by-translation-text :t/approved-amount-symbol {:amount "5" :symbol "ETH"})))
(h/test "on-press event is called when button is pressed"
(let [mock-fn (h/mock-fn)]
(h/render-with-theme-provider
[approval-label/view
{:status :approve
:customization-color :blue
:token-value "11"
:token-symbol "DAI"
:button-props {:on-press mock-fn}}])
(h/fire-event :press (h/get-by-translation-text :t/approve))
(h/was-called mock-fn))))
@@ -0,0 +1,14 @@
(ns quo.components.wallet.approval-label.schema)
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:status [:enum :approve :approving :approved]]
[:token-value :string]
[:token-symbol :string]
[:container-style {:optional true} [:maybe :map]]
[:button-props {:optional true} [:maybe :map]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]
:any])
@@ -0,0 +1,28 @@
(ns quo.components.wallet.approval-label.style
(:require [quo.foundations.colors :as colors]))
(def ^:const top-hole-view-height 24)
(defn container
[customization-color theme]
{:background-color (colors/resolve-color customization-color theme 5)
:align-items :center
:padding-horizontal 12
:padding-vertical 8
:padding-top (+ 8 top-hole-view-height)
:gap 8
:border-bottom-left-radius 16
:border-bottom-right-radius 16
:flex-direction :row})
(def content
{:flex-direction :row
:align-items :center
:flex 1
:padding-vertical 4
:gap 4})
(defn message
[theme]
{:flex 1
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
@@ -0,0 +1,70 @@
(ns quo.components.wallet.approval-label.view
(:require [oops.core :as oops]
[quo.components.buttons.button.view :as button]
[quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.components.wallet.approval-label.schema :as approval-label.schema]
[quo.components.wallet.approval-label.style :as style]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[schema.core :as schema]
[utils.i18n :as i18n]))
(def ^:private status-icons
{:approve :i/alert
:approving :i/pending-state
:approved :i/check})
(def ^:private status-message
{:approve :t/approve-amount-symbol
:approving :t/approving-amount-symbol
:approved :t/approved-amount-symbol})
(defn- view-internal
[{:keys [status token-value token-symbol
container-style button-props]
:as props}]
(let [theme (quo.theme/use-theme)
customization-color (or (:customization-color props) :blue)
[container-width set-container-width] (rn/use-state 0)
on-layout (rn/use-callback
#(set-container-width
(oops/oget % :nativeEvent :layout :width)))]
[hole-view/hole-view
{:holes [{:x 0
:y 0
:height style/top-hole-view-height
:width container-width
:borderBottomStartRadius 16
:borderBottomEndRadius 16}]
:style {:margin-top (- style/top-hole-view-height)}
:on-layout on-layout}
[rn/view
{:style (merge (style/container customization-color theme)
container-style)
:accessibility-label :approval-label}
[rn/view {:style style/content}
[icon/icon
(status-icons status)
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:size 16}]
[text/text
{:size :paragraph-2
:style (style/message theme)}
(i18n/label (status-message status)
{:amount token-value
:symbol token-symbol})]]
(when button-props
[button/button
(merge {:type (if (= status :approve) :primary :grey)
:background (when-not (= status :approve) :blur)
:customization-color customization-color
:size 24}
button-props)
(i18n/label (if (= status :approve)
:t/approve
:t/view))])]]))
(def view (schema/instrument #'view-internal approval-label.schema/?schema))
@@ -0,0 +1,24 @@
(ns quo.components.wallet.missing-keypairs.component-spec
(:require
[quo.components.wallet.missing-keypairs.view :as missing-keypairs]
[test-helpers.component :as h]))
(def ^:private theme :dark)
(def props
{:blur? true
:container-style {}
:on-options-press (fn [])
:keypairs [{:type :seed
:name name
:key-uid "123"
:accounts [{:customization-color :turquoise
:emoji "\uD83C\uDFB2"
:type :default}]}]})
(h/describe "Wallet: Missing key pairs"
(h/test "Missing key pair title renders"
(h/render-with-theme-provider [missing-keypairs/view props]
theme)
(h/is-truthy (h/get-by-label-text :title))
(h/is-truthy (h/get-by-label-text :t/import-to-use-derived-accounts))))
@@ -0,0 +1,28 @@
(ns quo.components.wallet.missing-keypairs.style
(:require
[quo.foundations.colors :as colors]))
(def container
{:border-width 1
:border-radius 16
:padding 8
:border-color colors/warning-50-opa-20
:background-color colors/warning-50-opa-5})
(def title-icon-container
{:top 1})
(def title-info-container
{:padding-left 8})
(def title-container
{:align-items :flex-start
:flex-direction :row
:padding-left 4
:padding-bottom 12})
(defn subtitle
[blur? theme]
{:color (if blur?
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
@@ -0,0 +1,53 @@
(ns quo.components.wallet.missing-keypairs.view
(:require
[quo.components.icon :as icon]
[quo.components.list-items.missing-keypair.view :as missing-keypair]
[quo.components.markdown.text :as text]
[quo.components.wallet.missing-keypairs.style :as style]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[utils.i18n :as i18n]))
(defn title-view
[{:keys [keypairs blur?]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :title
:style style/title-container}
[rn/view
{:style style/title-icon-container}
[icon/icon :i/info
{:size 20
:color colors/warning-60}]]
[rn/view
{:style style/title-info-container}
[text/text
{:weight :medium
:style {:color colors/warning-60}}
(i18n/label :t/amount-missing-keypairs
{:amount (str (count keypairs))})]
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}
(i18n/label :t/import-to-use-derived-accounts)]]]))
(defn- missing-keypair-item
[keypair _index _separators
{:keys [blur? on-options-press]}]
[missing-keypair/view
{:keypair keypair
:blur? blur?
:on-options-press on-options-press}])
(defn view
[{:keys [blur? keypairs container-style on-options-press] :as props}]
[rn/view
{:style (merge style/container container-style)}
[title-view props]
[rn/flat-list
{:data keypairs
:render-fn missing-keypair-item
:render-data {:blur? blur?
:on-options-press on-options-press}
:separator [rn/view {:style {:height 8}}]}]])
+14
View File
@@ -5,8 +5,11 @@
quo.components.avatars.account-avatar.view
quo.components.avatars.channel-avatar.view
quo.components.avatars.collection-avatar.view
quo.components.avatars.community-avatar.view
quo.components.avatars.dapp-avatar.view
quo.components.avatars.group-avatar.view
quo.components.avatars.icon-avatar
quo.components.avatars.token-avatar.view
quo.components.avatars.user-avatar.view
quo.components.avatars.wallet-user-avatar.view
quo.components.banners.banner.view
@@ -17,6 +20,7 @@
quo.components.buttons.logout-button.view
quo.components.buttons.predictive-keyboard.view
quo.components.buttons.slide-button.view
quo.components.buttons.swap-order-button.view
quo.components.buttons.wallet-button.view
quo.components.buttons.wallet-ctas.view
quo.components.calendar.calendar-day.view
@@ -84,6 +88,7 @@
quo.components.list-items.community.view
quo.components.list-items.dapp.view
quo.components.list-items.menu-item
quo.components.list-items.missing-keypair.view
quo.components.list-items.network-list.view
quo.components.list-items.preview-list.view
quo.components.list-items.quiz-item.view
@@ -165,8 +170,10 @@
quo.components.wallet.account-permissions.view
quo.components.wallet.address-text.view
quo.components.wallet.amount-input.view
quo.components.wallet.approval-label.view
quo.components.wallet.confirmation-progress.view
quo.components.wallet.keypair.view
quo.components.wallet.missing-keypairs.view
quo.components.wallet.network-amount.view
quo.components.wallet.network-bridge.view
quo.components.wallet.network-link.view
@@ -186,8 +193,11 @@
(def account-avatar quo.components.avatars.account-avatar.view/view)
(def channel-avatar quo.components.avatars.channel-avatar.view/view)
(def collection-avatar quo.components.avatars.collection-avatar.view/view)
(def community-avatar quo.components.avatars.community-avatar.view/view)
(def dapp-avatar quo.components.avatars.dapp-avatar.view/view)
(def group-avatar quo.components.avatars.group-avatar.view/view)
(def icon-avatar quo.components.avatars.icon-avatar/icon-avatar)
(def token-avatar quo.components.avatars.token-avatar.view/view)
(def user-avatar quo.components.avatars.user-avatar.view/user-avatar)
(def wallet-user-avatar quo.components.avatars.wallet-user-avatar.view/wallet-user-avatar)
@@ -201,6 +211,7 @@
(def logout-button quo.components.buttons.logout-button.view/view)
(def predictive-keyboard quo.components.buttons.predictive-keyboard.view/view)
(def slide-button quo.components.buttons.slide-button.view/view)
(def swap-order-button quo.components.buttons.swap-order-button.view/view)
(def wallet-button quo.components.buttons.wallet-button.view/view)
(def wallet-ctas quo.components.buttons.wallet-ctas.view/view)
@@ -317,6 +328,7 @@
(def community-list quo.components.list-items.community.view/view)
(def dapp quo.components.list-items.dapp.view/view)
(def menu-item quo.components.list-items.menu-item/menu-item)
(def missing-keypair quo.components.list-items.missing-keypair.view/view)
(def network-list quo.components.list-items.network-list.view/view)
(def preview-list quo.components.list-items.preview-list.view/view)
(def quiz-item quo.components.list-items.quiz-item.view/view)
@@ -434,8 +446,10 @@
(def account-permissions quo.components.wallet.account-permissions.view/view)
(def address-text quo.components.wallet.address-text.view/view)
(def amount-input quo.components.wallet.amount-input.view/view)
(def approval-label quo.components.wallet.approval-label.view/view)
(def confirmation-progress quo.components.wallet.confirmation-progress.view/view)
(def keypair quo.components.wallet.keypair.view/view)
(def missing-keypairs quo.components.wallet.missing-keypairs.view/view)
(def network-amount quo.components.wallet.network-amount.view/view)
(def network-bridge quo.components.wallet.network-bridge.view/view)
(def network-routing quo.components.wallet.network-routing.view/view)
+5
View File
@@ -1,6 +1,9 @@
(ns quo.core-spec
(:require
quo.components.avatars.account-avatar.component-spec
quo.components.avatars.community-avatar.component-spec
quo.components.avatars.dapp-avatar.component-spec
quo.components.avatars.token-avatar.component-spec
quo.components.avatars.user-avatar.component-spec
quo.components.banners.banner.component-spec
quo.components.browser.browser-input.component-spec
@@ -9,6 +12,7 @@
quo.components.buttons.logout-button.component-spec
quo.components.buttons.predictive-keyboard.component-spec
quo.components.buttons.slide-button.component-spec
quo.components.buttons.swap-order-button.component-spec
quo.components.buttons.wallet-button.component-spec
quo.components.buttons.wallet-ctas.component-spec
quo.components.calendar.calendar-day.component-spec
@@ -95,6 +99,7 @@
quo.components.wallet.account-overview.component-spec
quo.components.wallet.account-permissions.component-spec
quo.components.wallet.amount-input.component-spec
quo.components.wallet.approval-label.component-spec
quo.components.wallet.confirmation-progress.component-spec
quo.components.wallet.keypair.component-spec
quo.components.wallet.network-amount.component-spec
-37
View File
@@ -181,14 +181,6 @@
#(let [ret (handler)] (if (fn? ret) ret js/undefined))
(get-js-deps deps))))
(defn use-layout-effect
([handler]
(use-layout-effect handler nil))
([handler deps]
(react/useLayoutEffect
#(let [ret (handler)] (if (fn? ret) ret js/undefined))
(get-js-deps deps))))
(defn use-mount
[handler]
(use-effect handler []))
@@ -203,35 +195,6 @@
([handler deps]
(react/useCallback handler (get-js-deps deps))))
(defn use-fn-factory-factory
"A dirty code translation from the form-2 solution `make-fn-factory`."
[f]
(let [*args1 (use-ref-atom nil)
cached (use-ref-atom
(fn [& args2]
(apply f (concat @*args1 args2))))
factory (use-ref-atom
(fn factory
[& args1]
(reset! *args1 args1)
@cached))]
@factory))
(defn use-fn-factory
[f & args]
(let [factory (use-fn-factory-factory f)]
(apply factory args)))
(defn make-fn-factory
"Should be used in a form-2 component."
[f]
(let [*args1 (atom nil)
cached (fn [& args2]
(apply f (concat @*args1 args2)))]
(fn [& args1]
(reset! *args1 args1)
cached)))
(defn use-memo
[handler deps]
(react/useMemo handler (get-js-deps deps)))
+2 -2
View File
@@ -14,11 +14,11 @@
[{:keys [on-press allow-multiple-presses? throttle-duration]} throttle-id]
(if allow-multiple-presses?
on-press
(fn [event]
(fn []
(let [id @throttle-id]
(when (and id (not (get @throttle id)))
(swap! throttle assoc id true)
(on-press event)
(on-press)
(js/setTimeout
#(swap! throttle dissoc id)
(or throttle-duration 500)))))))
-9
View File
@@ -128,15 +128,6 @@
:user-picture-male4 (js/require "../resources/images/mock2/user_picture_male4.png")
:user-picture-male5 (js/require "../resources/images/mock2/user_picture_male5.png")})
(def services
{:latamex (js/require "../resources/images/services/Latamex.png")
:moonpay (js/require "../resources/images/services/Moonpay.png")
:ramp (js/require "../resources/images/services/Ramp.png")})
(defn get-service-image
[k]
(get services k))
(defn get-mock-image
[k]
(get mock-images k))
+16 -14
View File
@@ -20,7 +20,7 @@
(defonce camera-permission-granted? (reagent/atom false))
(defn- header
[{:keys [title subtitle]}]
[{:keys [title subtitle share-button?]}]
[:<>
[rn/view {:style style/header-container}
[quo/button
@@ -31,16 +31,17 @@
:accessibility-label :close-scan-qr-code
:on-press #(rf/dispatch [:navigate-back])}
:i/close]
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :show-qr-button
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/share-shell]))}
:i/qr-code]]
(when share-button?
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :show-qr-button
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/share-shell]))}
:i/qr-code])]
[quo/text
{:size :heading-1
:weight :semi-bold
@@ -195,7 +196,7 @@
true)
(defn view
[{:keys [title subtitle validate-fn on-success-scan error-message]}]
[{:keys [title subtitle validate-fn on-success-scan error-message share-button?]}]
(let [insets (safe-area/get-insets)
qr-code-succeed? (reagent/atom false)
qr-view-finder (reagent/atom {})
@@ -237,8 +238,9 @@
:set-rescan-timeout set-rescan-timeout}])
[rn/view {:style (style/root-container (:top insets))}
[header
{:title title
:subtitle subtitle}]
{:title title
:subtitle subtitle
:share-button? share-button?}]
(when (empty? @qr-view-finder)
[:<>
[rn/view {:style style/scan-qr-code-container}]
+2 -1
View File
@@ -35,7 +35,8 @@
(let [^js data (.parse js/JSON event-str)
^js event-js (.-event data)
type (.-type data)]
(log/debug "Signal received" event-str)
(log/debug "Signal received" {:type type})
(log/trace "Signal received" {:payload event-str})
(case type
"node.login" {:fx [[:dispatch
[:profile.login/login-node-signal
@@ -24,7 +24,7 @@
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
:auth-button-label auth-button-label}]))
(into [] (concat [theme] dependencies)))]
(vec (conj dependencies on-auth-success on-auth-fail)))]
[quo/slide-button
{:container-style container-style
:size size
+5 -22
View File
@@ -26,7 +26,7 @@
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
(goog-define WALLET_CONNECT_PROJECT_ID "")
(def mainnet-rpc-url (str "https://eth-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
(def mainnet-chain-explorer-link "https://etherscan.io/address/")
(def optimism-mainnet-chain-explorer-link "https://optimistic.etherscan.io/address/")
@@ -105,32 +105,15 @@
(def fast-create-community-enabled?
(enabled? (get-config :FAST_CREATE_COMMUNITY_ENABLED "0")))
(def default-multiaccount
{:preview-privacy? blank-preview?
:wallet-legacy/visible-tokens {:mainnet #{:SNT}}
:currency :usd
:appearance 0
:profile-pictures-show-to 2
:profile-pictures-visibility 2
:log-level log-level
:webview-allow-permission-requests? false
:opensea-enabled? false
:link-previews-enabled-sites #{}
:link-preview-request-enabled true})
(defn default-visible-tokens
[chain]
(get-in default-multiaccount [:wallet-legacy/visible-tokens chain]))
(def waku-nodes-config
{:status.prod
["enrtree://AL65EKLJAUXKKPG43HVTML5EFFWEZ7L4LOKTLZCLJASG4DSESQZEC@prod.status.nodes.status.im"]
:status.test
["enrtree://AIO6LUM3IVWCU2KCPBBI6FEH2W42IGK3ASCZHZGG5TIXUR56OGQUO@test.status.nodes.status.im"]
:wakuv2.prod
["enrtree://ANEDLO25QVUGJOUTQFRYKWX6P4Z4GKVESBMHML7DZ6YK4LGS5FC5O@prod.wakuv2.nodes.status.im"]
:wakuv2.test
["enrtree://AO47IDOLBKH72HIZZOXQP6NMRESAN7CHYWIBNXDXWRJRZWLODKII6@test.wakuv2.nodes.status.im"]})
:waku.sandbox
["enrtree://AIRVQ5DDA4FFWLRBCHJWUWOO6X6S4ZTZ5B667LQ6AJU6PEYDLRD5O@sandbox.waku.nodes.status.im"]
:waku.test
["enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im"]})
(def default-kdf-iterations 3200)
@@ -5,32 +5,25 @@
[theme]
{:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
:justify-content :space-between
:align-items :center
:margin-top 2
:padding-horizontal 20})
(def container-invalid
{:style {:flex-direction :row
:align-items :center
:margin-top 8}})
{:flex-direction :row
:margin-top 8})
(defn text-description
[theme]
{:size :paragraph-2
:weight :medium
:style {:margin-bottom 6
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}})
{:margin-bottom 6
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(def icon-invalid
{:size 16
:color colors/danger-50})
(def text-invalid
{:size :paragraph-2
:align :left
:style {:margin-left 4
:color colors/danger-50}})
{:margin-left 4
:color colors/danger-50})
(def input-and-scan-container
{:flex-direction :row
@@ -18,7 +18,10 @@
theme (quo.theme/use-theme)]
(when primary-name
[rn/view style/found-user
[quo/text (style/text-description theme)
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/text-description theme)}
(i18n/label :t/user-found)]
[rn/view (style/found-user-container theme)
[quo/user-avatar
@@ -105,7 +108,9 @@
[message]
[rn/view style/container-invalid
[quo/icon :i/alert style/icon-invalid]
[quo/text style/text-invalid
[quo/text
{:size :paragraph-2
:style style/text-invalid}
(i18n/label (or message :t/invalid-ens-or-key))]])
(defn navigate-back [] (rf/dispatch [:navigate-back]))
@@ -187,29 +187,29 @@
muted? (and muted (some? muted-till))
mute-chat-label (if community-channel? :t/mute-channel :t/mute-chat)
unmute-chat-label (if community-channel? :t/unmute-channel :t/unmute-chat)]
[quo/channel-actions
{:actions [{:accessibility-label :action-button-pinned
:big? true
:label (or latest-pin-text (i18n/label :t/no-pinned-messages))
:customization-color cover-bg-color
:icon :i/pin
:counter-value pins-count
:on-press (fn []
(rf/dispatch [:pin-message/show-pins-bottom-sheet
chat-id]))}
{:accessibility-label :action-button-mute
:label (i18n/label (if muted
unmute-chat-label
mute-chat-label))
:customization-color cover-bg-color
:icon (if muted? :i/activity-center :i/muted)
:on-press (fn []
(if muted?
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id
chat-type
muted?)))}]}]))
{:actions
[{:accessibility-label :action-button-pinned
:big? true
:label (if (pos? pins-count) latest-pin-text (i18n/label :t/no-pinned-messages))
:customization-color cover-bg-color
:icon :i/pin
:counter-value pins-count
:on-press (fn []
(rf/dispatch [:pin-message/show-pins-bottom-sheet
chat-id]))}
{:accessibility-label :action-button-mute
:label (i18n/label (if muted
unmute-chat-label
mute-chat-label))
:customization-color cover-bg-color
:icon (if muted? :i/activity-center :i/muted)
:on-press (fn []
(if muted?
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id
chat-type
muted?)))}]}]))
(defn bio-and-actions
[{:keys [distance-from-list-top bio chat-id customization-color empty-chat? description]}]
@@ -14,7 +14,7 @@
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
(h/is-truthy (h/get-by-translation-text :t/mark-as-read))
(h/is-truthy (h/get-by-translation-text :t/mute-community))
(h/is-truthy (h/get-by-translation-text :t/notification-settings))
;(h/is-truthy (h/get-by-translation-text :t/notification-settings))
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
(h/is-truthy (h/get-by-translation-text :t/show-qr))
(h/is-truthy (h/get-by-translation-text :t/share-community))
@@ -30,7 +30,7 @@
(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
(h/is-truthy (h/get-by-translation-text :t/mark-as-read))
(h/is-truthy (h/get-by-translation-text :t/mute-community))
(h/is-truthy (h/get-by-translation-text :t/notification-settings))
;(h/is-truthy (h/get-by-translation-text :t/notification-settings))
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
(h/is-truthy (h/get-by-translation-text :t/show-qr))
(h/is-truthy (h/get-by-translation-text :t/share-community))
@@ -44,7 +44,7 @@
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
(h/is-truthy (h/get-by-translation-text :t/mark-as-read))
(h/is-truthy (h/get-by-translation-text :t/mute-community))
(h/is-truthy (h/get-by-translation-text :t/notification-settings))
;(h/is-truthy (h/get-by-translation-text :t/notification-settings))
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
(h/is-truthy (h/get-by-translation-text :t/show-qr))
(h/is-truthy (h/get-by-translation-text :t/share-community)))
@@ -58,7 +58,7 @@
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
(h/is-truthy (h/get-by-translation-text :t/mark-as-read))
(h/is-truthy (h/get-by-translation-text :t/mute-community))
(h/is-truthy (h/get-by-translation-text :t/notification-settings))
;(h/is-truthy (h/get-by-translation-text :t/notification-settings))
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
(h/is-truthy (h/get-by-translation-text :t/show-qr))
(h/is-truthy (h/get-by-translation-text :t/share-community)))
@@ -3,6 +3,7 @@
[quo.core :as quo]
[status-im.common.mute-drawer.view :as mute-options]
[status-im.common.muting.helpers :refer [format-mute-till]]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.communities.actions.leave.view :as leave-menu]
[status-im.contexts.communities.actions.permissions-sheet.view :as permissions-sheet]
@@ -83,11 +84,12 @@
(defn community-notification-settings
[id]
{:icon :i/notifications
:accessibility-label :community-notification-settings
:label (i18n/label :t/notification-settings)
:on-press #(js/alert (str "implement action" id))
:right-icon :i/chevron-right})
(when config/show-not-implemented-features?
{:icon :i/notifications
:accessibility-label :community-notification-settings
:label (i18n/label :t/notification-settings)
:on-press #(js/alert (str "implement action" id))
:right-icon :i/chevron-right}))
(defn invite-contacts
[id]
+17 -8
View File
@@ -241,6 +241,13 @@
(rf/reg-event-fx :chat.ui/community-failed-to-fetch community-failed-to-fetch)
(defn- failed-to-fetch-community
[community-id err]
(rf/dispatch [:chat.ui/community-failed-to-fetch community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))
(defn fetch-community
[{:keys [db]} [{:keys [community-id update-last-opened-at?]}]]
(when (and community-id (not (get-in db [:communities/fetching-communities community-id])))
@@ -250,14 +257,16 @@
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(when update-last-opened-at?
(rf/dispatch [:communities/update-last-opened-at community-id]))
(rf/dispatch [:chat.ui/community-fetched community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-fetch community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(if community
(do (when update-last-opened-at?
(rf/dispatch [:communities/update-last-opened-at
community-id]))
(rf/dispatch [:chat.ui/community-fetched community-id
community]))
(failed-to-fetch-community
community-id
"community wasn't found at the store node")))
:on-error (partial failed-to-fetch-community community-id)}]}))
(schema/=> fetch-community
[:=>
@@ -2,6 +2,7 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.config :as config]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.syncing.progress.style :as style]
[utils.debounce :as debounce]
@@ -54,11 +55,13 @@
(when-not in-onboarding? [background/view true])
[quo/page-nav {:type :no-title :background :blur}]
[page-title (pairing-progress pairing-status)]
(if (pairing-progress pairing-status)
[rn/view {:style style/page-illustration}
[quo/text "[Success here]"]]
[rn/view {:style style/page-illustration}
[quo/text "[Error here]"]])
(if config/show-not-implemented-features?
(if (pairing-progress pairing-status)
[rn/view {:style style/page-illustration}
[quo/text "[Success here]"]]
[rn/view {:style style/page-illustration}
[quo/text "[Error here]"]])
[rn/view {:flex 1}])
(when-not (pairing-progress pairing-status)
[try-again-button profile-color in-onboarding? logged-in?])]))
@@ -0,0 +1,24 @@
(ns status-im.contexts.preview.quo.avatars.community-avatar
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :select
:key :size
:options [{:key :size-32}
{:key :size-24}]}])
(defn view
[]
(let [[state set-state] (rn/use-state {:size :size-32})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/community-avatar
(assoc state
:image
(resources/get-mock-image :community-logo))]]))
@@ -0,0 +1,22 @@
(ns status-im.contexts.preview.quo.avatars.dapp-avatar
(:require
[quo.core :as quo]
[quo.foundations.resources :as resources]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :boolean
:key :context?}])
(defn view
[]
(let [[state set-state] (rn/use-state {:context? false})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/dapp-avatar
(assoc state
:network-image (resources/get-network :ethereum)
:image (resources/get-dapp :coingecko))]]))
@@ -0,0 +1,29 @@
(ns status-im.contexts.preview.quo.avatars.token-avatar
(:require
[quo.core :as quo]
[quo.foundations.resources :as foundations.resources]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :select
:key :type
:options [{:key :asset}
{:key :collectible}]}
{:type :boolean
:key :context?}])
(defn view
[]
(let [[state set-state] (rn/use-state {:type :asset
:context? false})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/token-avatar
(assoc state
:network-image (foundations.resources/get-network :optimism)
:image (resources/get-mock-image
(if (= (state :type) :asset) :status-logo :collectible1)))]]))
@@ -0,0 +1,21 @@
(ns status-im.contexts.preview.quo.buttons.swap-order-button
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :boolean
:key :disabled?}])
(defn view
[]
(let [[state set-state] (rn/use-state {:disabled? false})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/swap-order-button
(assoc state
:on-press
#(js/alert "Pressed"))]]))
@@ -25,8 +25,11 @@
:value "null"}]}
{:key :blur?
:type :boolean}
{:key :keycard?
:type :boolean}
{:key :stored
:type :select
:options [{:key :on-device}
{:key :on-keycard}
{:key :missing}]}
{:key :title
:type :text}
{:key :description
@@ -44,7 +47,7 @@
:title "Title"
:type :default
:label "Drawer label"
:keycard? true
:stored :on-device
:networks [{:network-name :ethereum :short-name "eth"}]
:description "0x62b...0a5"
:button-icon :i/placeholder
@@ -0,0 +1,32 @@
(ns status-im.contexts.preview.quo.list-items.missing-keypair
(:require
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:key :blur?
:type :boolean}])
(def component-props
{:blur? false
:keypair {:type :seed
:key-uid "0x01"
:name "Trip to Vegas"
:accounts [{:type :default
:emoji "🍑"
:customization-color :purple}]}})
(defn view
[]
(let [state (reagent/atom component-props)]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true
:blur-dark-only? true}
[rn/view {:style {:align-items :flex-start}}
[quo/missing-keypair @state]]])))
+22 -1
View File
@@ -10,8 +10,11 @@
[status-im.contexts.preview.quo.avatars.account-avatar :as account-avatar]
[status-im.contexts.preview.quo.avatars.channel-avatar :as channel-avatar]
[status-im.contexts.preview.quo.avatars.collection-avatar :as collection-avatar]
[status-im.contexts.preview.quo.avatars.community-avatar :as community-avatar]
[status-im.contexts.preview.quo.avatars.dapp-avatar :as dapp-avatar]
[status-im.contexts.preview.quo.avatars.group-avatar :as group-avatar]
[status-im.contexts.preview.quo.avatars.icon-avatar :as icon-avatar]
[status-im.contexts.preview.quo.avatars.token-avatar :as token-avatar]
[status-im.contexts.preview.quo.avatars.user-avatar :as user-avatar]
[status-im.contexts.preview.quo.avatars.wallet-user-avatar :as
wallet-user-avatar]
@@ -24,6 +27,7 @@
[status-im.contexts.preview.quo.buttons.predictive-keyboard :as
predictive-keyboard]
[status-im.contexts.preview.quo.buttons.slide-button :as slide-button]
[status-im.contexts.preview.quo.buttons.swap-order-button :as swap-order-button]
[status-im.contexts.preview.quo.buttons.wallet-button :as wallet-button]
[status-im.contexts.preview.quo.buttons.wallet-ctas :as wallet-ctas]
[status-im.contexts.preview.quo.calendar.calendar :as calendar]
@@ -102,6 +106,7 @@
[status-im.contexts.preview.quo.list-items.address :as address]
[status-im.contexts.preview.quo.list-items.channel :as channel]
[status-im.contexts.preview.quo.list-items.dapp :as dapp]
[status-im.contexts.preview.quo.list-items.missing-keypair :as missing-keypair]
[status-im.contexts.preview.quo.list-items.network-list :as network-list]
[status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists]
[status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item]
@@ -191,9 +196,11 @@
account-overview]
[status-im.contexts.preview.quo.wallet.account-permissions :as account-permissions]
[status-im.contexts.preview.quo.wallet.amount-input :as amount-input]
[status-im.contexts.preview.quo.wallet.approval-label :as approval-label]
[status-im.contexts.preview.quo.wallet.confirmation-progress :as
confirmation-progress]
[status-im.contexts.preview.quo.wallet.keypair :as keypair]
[status-im.contexts.preview.quo.wallet.missing-keypairs :as missing-keypairs]
[status-im.contexts.preview.quo.wallet.network-amount :as network-amount]
[status-im.contexts.preview.quo.wallet.network-bridge :as network-bridge]
[status-im.contexts.preview.quo.wallet.network-link :as network-link]
@@ -216,10 +223,16 @@
:component shadows/view}]
:animated-list [{:name :animated-header-list
:component animated-header-list/mock-screen}]
:avatar [{:name :group-avatar
:avatar [{:name :community-avatar
:component community-avatar/view}
{:name :dapp-avatar
:component dapp-avatar/view}
{:name :group-avatar
:component group-avatar/view}
{:name :icon-avatar
:component icon-avatar/view}
{:name :token-avatar
:component token-avatar/view}
{:name :user-avatar
:component user-avatar/view}
{:name :wallet-user-avatar
@@ -240,6 +253,8 @@
:component dynamic-button/view}
{:name :slide-button
:component slide-button/view}
{:name :swap-order-button
:component swap-order-button/view}
{:name :predictive-keyboard
:component predictive-keyboard/view}
{:name :wallet-button
@@ -376,6 +391,8 @@
:component community-list-item/view}
{:name :dapp
:component dapp/preview}
{:name :missing-keypair
:component missing-keypair/view}
{:name :network-list
:component network-list/view}
{:name :preview-lists
@@ -526,9 +543,13 @@
:component account-permissions/view}
{:name :amount-input
:component amount-input/view}
{:name :approval-label
:component approval-label/view}
{:name :confirmation-progress
:component confirmation-progress/view}
{:name :keypair :component keypair/view}
{:name :missing-keypairs
:component missing-keypairs/view}
{:name :network-amount :component network-amount/view}
{:name :network-bridge :component network-bridge/view}
{:name :network-link :component network-link/view}
@@ -0,0 +1,37 @@
(ns status-im.contexts.preview.quo.wallet.approval-label
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :select
:key :status
:options [{:key :approve}
{:key :approving}
{:key :approved}]}
{:type :text
:key :token-value}
{:type :select
:key :token-symbol
:options [{:key "SNT"}
{:key "DAI"}
{:key "ETH"}]}
(preview/customization-color-option)])
(defn view
[]
(let [[state set-state] (rn/use-state {:status :approve
:customization-color :blue
:token-value "100"
:token-symbol "SNT"})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor
:component-container-style {:padding-top 50}}
[quo/approval-label
(assoc state
:button-props
{:on-press
#(js/alert "Pressed")})]]))
@@ -0,0 +1,57 @@
(ns status-im.contexts.preview.quo.wallet.missing-keypairs
(:require
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.contexts.preview.quo.preview :as preview]))
(def keypair
{:key-uid "0x01"
:type "seed"
:name "My Key Pair"
:blur? false})
(def accounts
[{:customization-color :turquoise
:emoji "\uD83C\uDFB2"
:type :default}
{:customization-color :purple
:emoji "\uD83C\uDF7F"
:type :default}
{:customization-color :army
:emoji "\uD83D\uDCC8"
:type :default}
{:customization-color :orange
:emoji "\uD83C\uDFF0"
:type :default}
{:customization-color :yellow
:emoji "\uD83C\uDFDD"
:type :default}])
(def descriptor
[{:key :blur? :type :boolean}])
(def component-props
{:blur? false
:keypairs [{:name (:name keypair)
:key-uid (:key-uid keypair)
:type (keyword (:type keypair))
:accounts accounts}]})
(defn view
[]
(let [state (reagent/atom {:blur? false})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true
:blur-dark-only? true
:blur-height 400
:component-container-style {:padding-vertical 30
:flex-direction :row
:justify-content :center}}
[rn/view {:style {:flex 1}}
[quo/missing-keypairs
(merge component-props @state)]]])))
@@ -3,173 +3,32 @@
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.ratom]
[status-im.constants :as constants]
[status-im.contexts.profile.contact.contact-request.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
;; ---
(def ^:private lookup-sentinel (js-obj))
(defn memo
"Returns a memoized version of a referentially transparent function. The
memoized version of the function keeps a cache of the mapping from arguments
to results and, when calls with the same arguments are repeated often, has
higher performance at the expense of higher memory use."
[mem f]
(fn [& args]
(js/console.log "lookup")
(let [v (get @mem args lookup-sentinel)]
(if (identical? v lookup-sentinel)
(let [ret (apply f args)]
(js/console.log "swap")
(swap! mem assoc args ret)
ret)
v))))
(defn make-snapshot-handler-factory
[snapshot]
(let [storage (rn/use-memo #(atom {}) [])
capture (rn/use-memo #(atom snapshot) [])
_update (rn/use-layout-effect
(fn []
(swap! capture (fn [_] snapshot)))
snapshot)
factory (rn/use-memo
(fn []
(fn [handler]
((memo storage
(fn [callback]
(fn [event]
(callback @capture event))))
handler)))
[storage capture])]
{:factory factory
:storage storage}))
(defn use-bind-snapshot
[snapshot]
(let [{:keys [factory storage]}
(make-snapshot-handler-factory snapshot)]
(rn/use-unmount (fn []
(js/console.log "unmount bind-snapshot")
(prn "unmount storage" storage)))
factory))
;; ---
(defn on-message-submit
[public-key message _event]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:contact.ui/send-contact-request public-key message])
(rf/dispatch [:toasts/upsert
{:id :send-contact-request
:type :positive
:text (i18n/label
:t/contact-request-was-sent)}]))
(defn on-message-change
[set-message full-name message-text]
;; This is just an example tap to check that when full-name is recomputed,
;; this function sees the most up-to-date value.
(tap> [:on-message-change full-name message-text])
(set-message message-text))
(defn use-event
[f scope]
(let [bind (use-bind-snapshot scope)]
(bind f)))
(defn use-events
[fs scope]
(let [bind (use-bind-snapshot scope)]
(->> fs
(reduce-kv
(fn [acc label f]
(assoc acc label (bind f)))
{}))))
(defn view--using-factory-with-form-2
[]
(let [on-change-factory (rn/make-fn-factory on-message-change)
on-submit-factory (rn/make-fn-factory on-message-submit)]
(fn []
(let [{:keys [public-key customization-color]
:as profile} (rf/sub [:contacts/current-contact])
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
input-ref (rn/use-ref-atom nil)
[message set-message] (rn/use-state "")
on-change (on-change-factory set-message full-name)
on-submit (on-submit-factory public-key message)]
(rn/use-mount
(fn []
(let [listener (.addListener rn/keyboard
"keyboardDidHide"
(fn [_event]
(when (and platform/android? @input-ref)
(.blur ^js @input-ref))))]
#(.remove ^js listener))))
[:<>
[quo/drawer-top
{:type :context-tag
:context-tag-type :default
:title (i18n/label :t/send-contact-request)
:full-name full-name
:profile-picture profile-picture
:customization-color customization-color}]
[quo/text {:style style/message-prompt-wrapper}
(i18n/label :t/contact-request-message-prompt)]
[rn/view {:style style/message-input-wrapper}
[quo/input
{:type :text
:ref #(reset! input-ref %)
:multiline? true
:char-limit constants/contact-request-message-max-length
:max-length constants/contact-request-message-max-length
:placeholder (i18n/label :t/type-something)
:auto-focus true
:accessibility-label :contact-request-message
:label (i18n/label :t/message)
:on-change-text on-change
:container-style {:flex-shrink 1}
:input-container-style {:flex-shrink 1}}]]
[quo/bottom-actions
{:container-style {:style {:flex 1}}
:actions :one-action
:button-one-props {:disabled? (string/blank? message)
:accessibility-label :send-contact-request
:customization-color :purple
:on-press on-submit}
:button-one-label "Past Present Sub"}]
[quo/bottom-actions
{:container-style {:style {:flex 1}}
:actions :two-actions
:button-one-props {:accessibility-label :send-contact-request
:customization-color :blue
:on-press on-submit}
:button-one-label "Snapshot"
:button-two-props {:accessibility-label :test-button
:customization-color :orange
:on-press on-submit}
:button-two-label "Sub"}]]))))
(defn view--using-factory-hook
(defn view
[]
(let [{:keys [public-key customization-color]
:as profile} (rf/sub [:contacts/current-contact])
customization-color customization-color
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
input-ref (rn/use-ref-atom nil)
[message set-message] (rn/use-state "")
on-change (rn/use-fn-factory on-message-change set-message full-name)
on-submit (rn/use-fn-factory on-message-submit public-key message)]
;; `on-change` is always the same function instance, even if the arguments
;; `set-message` and `full-name` change.
(tap> {:hashes {:on-change (hash on-change)}})
on-message-change (rn/use-callback #(set-message %))
on-message-submit (rn/use-callback (fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:contact.ui/send-contact-request
public-key message])
(rf/dispatch [:toasts/upsert
{:id :send-contact-request
:type :positive
:text (i18n/label
:t/contact-request-was-sent)}]))
[public-key message])]
(rn/use-mount
(fn []
(let [listener (.addListener rn/keyboard
@@ -199,7 +58,7 @@
:auto-focus true
:accessibility-label :contact-request-message
:label (i18n/label :t/message)
:on-change-text on-change
:on-change-text on-message-change
:container-style {:flex-shrink 1}
:input-container-style {:flex-shrink 1}}]]
[quo/bottom-actions
@@ -207,19 +66,7 @@
:actions :one-action
:button-one-props {:disabled? (string/blank? message)
:accessibility-label :send-contact-request
:customization-color :purple
:on-press on-submit}
:button-one-label "Past Present Sub"}]
[quo/bottom-actions
{:container-style {:style {:flex 1}}
:actions :two-actions
:button-one-props {:accessibility-label :send-contact-request
:customization-color :blue
:on-press on-submit}
:button-one-label "Snapshot"
:button-two-props {:accessibility-label :test-button
:customization-color :orange
:on-press on-submit}
:button-two-label "Sub"}]]))
:customization-color customization-color
:on-press on-message-submit}
:button-one-label (i18n/label :t/send-contact-request)}]]))
(def view view--using-factory-hook)
@@ -16,3 +16,10 @@
(def keypair-container-style
{:margin-horizontal 20
:margin-vertical 8})
(def missing-keypairs-container-style
{:margin-horizontal 20
:margin-vertical 8})
(def settings-keypairs-container
{:flex 1})
@@ -20,6 +20,21 @@
{:content (fn [] [actions/view props keypair])
:theme theme}]))
(defn options-drawer-props
[{{:keys [name]} :keypair
:keys [type stored theme shortened-key customization-color profile-picture]}]
(cond-> {:theme theme
:type type
:blur? true
:title name
:stored stored}
(= type :default-keypair)
(assoc :description shortened-key
:customization-color customization-color
:profile-picture profile-picture)
(= type :keypair)
(assoc :icon-avatar :i/seed)))
(defn- keypair
[{keypair-type :type
:keys [accounts name]
@@ -33,22 +48,19 @@
on-press (rn/use-callback
(fn []
(on-options-press
(cond-> {:theme theme
:blur? true
:title name}
default-keypair?
(assoc :type :default-keypair
:description shortened-key
:customization-color customization-color
:profile-picture profile-picture)
(not default-keypair?)
(assoc :type :keypair
:icon-avatar :i/seed))
(options-drawer-props
{:theme theme
:keypair item
:type (if default-keypair? :default-keypair :keypair)
:stored :on-device
:shortened-key shortened-key
:customization-color customization-color
:profile-picture profile-picture})
item))
[customization-color default-keypair? name
[customization-color default-keypair? item
profile-picture shortened-key theme])]
[quo/keypair
{:blur? false
{:blur? true
:status-indicator false
:stored :on-device
:action :options
@@ -61,13 +73,27 @@
:details {:full-name name
:address shortened-key}}]))
(defn on-missing-keypair-options-press
[_event keypair-data]
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:content (fn [] [actions/view
(options-drawer-props
{:theme :dark
:type :keypair
:stored :missing
:blur? true
:keypair keypair-data})
keypair-data])}]))
(defn view
[]
(let [insets (safe-area/get-insets)
compressed-key (rf/sub [:profile/compressed-key])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])
quo-keypairs-accounts (rf/sub [:wallet/settings-keypairs-accounts])]
(let [insets (safe-area/get-insets)
compressed-key (rf/sub [:profile/compressed-key])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])
{missing-keypairs :missing
operable-keypairs :operable} (rf/sub [:wallet/settings-keypairs-accounts])]
[quo/overlay
{:type :shell
:container-style (style/page-wrapper (:top insets))}
@@ -81,9 +107,15 @@
{:title (i18n/label :t/keypairs-and-accounts)
:accessibility-label :keypairs-and-accounts-header
:customization-color customization-color}]]
[rn/view {:style {:flex 1}}
[rn/view {:style style/settings-keypairs-container}
(when (seq missing-keypairs)
[quo/missing-keypairs
{:blur? true
:keypairs missing-keypairs
:container-style style/missing-keypairs-container-style
:on-options-press on-missing-keypair-options-press}])
[rn/flat-list
{:data quo-keypairs-accounts
{:data operable-keypairs
:render-fn keypair
:render-data {:profile-picture profile-picture
:compressed-key compressed-key
@@ -6,6 +6,7 @@
[react-native.gesture :as gesture]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im.config :as config]
[status-im.contexts.shell.jump-to.animation :as animation]
[status-im.contexts.shell.jump-to.components.bottom-tabs.style :as style]
[status-im.contexts.shell.jump-to.constants :as shell.constants]
@@ -70,4 +71,5 @@
[gesture/gesture-detector {:gesture messages-double-tap-gesture}
[bottom-tab :i/messages :chats-stack shared-values notifications-data]]
[bottom-tab :i/wallet :wallet-stack shared-values notifications-data]
[bottom-tab :i/browser :browser-stack shared-values notifications-data]]]]))
(when config/show-not-implemented-features?
[bottom-tab :i/browser :browser-stack shared-values notifications-data])]]]))
@@ -118,6 +118,7 @@
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:share-button? true
:on-success-scan on-qr-code-scanned}]]))
(defn view
@@ -19,11 +19,12 @@
(h/before-each
(fn []
(h/setup-subs {:dimensions/window-width 500
:mediaserver/port 200
:wallet/accounts [{:address "0x707f635951193ddafbb40971a0fcaab8a6415160"
:name "Wallet One"
:emoji "😆"
:color :blue}]})))
:mediaserver/port 200
:wallet/accounts [{:address "0x707f635951193ddafbb40971a0fcaab8a6415160"
:name "Wallet One"
:emoji "😆"
:color :blue}]
:wallet/preferred-chain-names-for-address #{:eth :oeth :arb1}})))
(h/test "should display the wallet tab"
(render-wallet-view)
@@ -5,7 +5,6 @@
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im.constants :as constants]
[status-im.contexts.shell.share.style :as style]
[status-im.contexts.shell.share.wallet.style :as wallet-style]
[status-im.contexts.wallet.common.utils :as utils]
@@ -51,9 +50,9 @@
chain-ids)))}])}]))
(defn- wallet-qr-code-item
[{:keys [account index]}]
[{:keys [account index preferred-chains]}]
(let [{window-width :width} (rn/get-window)
selected-networks (reagent/atom constants/default-network-names)
selected-networks (reagent/atom preferred-chains)
wallet-type (reagent/atom :multichain)
on-settings-press #(open-preferences selected-networks account)
on-legacy-press #(reset! wallet-type :legacy)
@@ -97,10 +96,11 @@
^{:key i} [indicator (= current-index i)])])
(defn render-item
[item]
[{:keys [address] :as account}]
[wallet-qr-code-item
{:account item
:index (:position item)}])
{:account account
:index (:position account)
:preferred-chains (rf/sub [:wallet/preferred-chain-names-for-address address])}])
(defn- qr-code-visualized-index
[offset qr-code-size num-qr-codes]
@@ -47,13 +47,10 @@
:shell? true
:content sheet-content}])))
(defn view
[]
(let [padding-top (:top (safe-area/get-insets))
wallet-type (reagent/atom :legacy)
;; Design team is yet to confirm the default selected networks here. Should be the current
;; selected for the account or all the networks always
selected-networks (reagent/atom constants/default-network-names)
on-settings-press #(open-preferences selected-networks)
on-legacy-press #(reset! wallet-type :legacy)
@@ -61,11 +58,11 @@
(fn []
(let [{:keys [address color emoji watch-only?]
:as account} (rf/sub [:wallet/current-viewing-account])
preferred-networks (rf/sub [:wallet/preferred-chain-names-for-address address])
share-title (str (:name account) " " (i18n/label :t/address))
qr-url (utils/get-wallet-qr {:wallet-type @wallet-type
:selected-networks
@selected-networks
:address address})
qr-url (utils/get-wallet-qr {:wallet-type @wallet-type
:selected-networks @selected-networks
:address address})
qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
{:url qr-url
:port (rf/sub [:mediaserver/port])
@@ -76,6 +73,9 @@
:share (i18n/label :t/share-address)
:receive (i18n/label :t/receive)
nil)]
(rn/use-mount #(reset! selected-networks preferred-networks))
[quo/overlay {:type :shell}
[rn/view
{:flex 1
@@ -11,6 +11,22 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- on-collectible-press
[{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:name (:name collectible-details)
:image (:uri preview-url)}])}]))
(defn- on-end-reached
[]
(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account]))
(defn view
[{:keys [selected-tab]}]
(let [collectible-list (rf/sub
@@ -20,19 +36,11 @@
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view
{:collectibles collectible-list
:current-account-address current-account-address
:on-end-reached #(rf/dispatch
[:wallet/request-collectibles-for-current-viewing-account])
:on-collectible-press (fn [{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))
:on-collectible-long-press (fn [{:keys [preview-url collectible-details]}]
(rf/dispatch
[:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:name (:name collectible-details)
:image (:uri preview-url)}])}]))}]
{:collectibles collectible-list
:current-account-address current-account-address
:on-end-reached on-end-reached
:on-collectible-press on-collectible-press
:on-collectible-long-press on-collectible-long-press}]
:activity [activity/view]
:permissions [empty-tab/view
{:title (i18n/label :t/no-permissions)
@@ -28,6 +28,7 @@
(let [{:keys [name color formatted-balance
watch-only?]} (rf/sub [:wallet/current-viewing-account])
customization-color (rf/sub [:profile/customization-color])]
(rn/use-unmount #(rf/dispatch [:wallet/close-account-page]))
[rn/view {:style {:flex 1}}
[account-switcher/view
{:type :wallet-networks
@@ -38,8 +38,7 @@
:disabled? (string/blank? @account-name)
:accessibility-label :confirm-button-label
:on-press #(rf/dispatch [:wallet/add-account
{:sha3-pwd nil
:type :watch
{:type :watch
:account-name @account-name
:emoji @account-emoji
:color @account-color}
@@ -1,6 +1,10 @@
(ns status-im.contexts.wallet.add-account.create-account.events
(:require [camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.data-store :as data-store]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as transforms]))
@@ -22,14 +26,18 @@
(rf/reg-event-fx :wallet/confirm-account-origin confirm-account-origin)
(defn store-seed-phrase
(defn store-new-seed-phrase
[{:keys [db]} [{:keys [seed-phrase random-phrase]}]]
{:db (-> db
(assoc-in [:wallet :ui :create-account :seed-phrase] seed-phrase)
(assoc-in [:wallet :ui :create-account :random-phrase] random-phrase))
:fx [[:dispatch-later [{:ms 20 :dispatch [:navigate-to :screen/wallet.confirm-backup]}]]]})
{:db (update-in db
[:wallet :ui :create-account :new-keypair]
assoc
:seed-phrase seed-phrase
:random-phrase random-phrase)
:fx [[:dispatch-later
[{:ms 20
:dispatch [:navigate-to :screen/wallet.confirm-backup]}]]]})
(rf/reg-event-fx :wallet/store-seed-phrase store-seed-phrase)
(rf/reg-event-fx :wallet/store-new-seed-phrase store-new-seed-phrase)
(defn seed-phrase-validated
[{:keys [db]} [seed-phrase]]
@@ -43,33 +51,45 @@
{:fx [[:multiaccount/validate-mnemonic
[seed-phrase
(fn [mnemonic key-uid]
(rf/dispatch [:wallet/seed-phrase-validated
mnemonic key-uid]))
(rf/dispatch [:wallet/seed-phrase-validated mnemonic key-uid]))
on-error]]]})
(rf/reg-event-fx :wallet/seed-phrase-entered seed-phrase-entered)
(defn new-keypair-created
[{:keys [db]} [{:keys [new-keypair]}]]
{:db (assoc-in db [:wallet :ui :create-account :new-keypair] new-keypair)
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]})
(defn store-account-generated
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
(let [new-account (update new-account-data :mnemonic security/mask-data)]
{:db (-> db
(update-in [:wallet :ui :create-account :new-keypair]
assoc
:new-account-data new-account
:keypair-name keypair-name)
(update-in [:wallet :ui :create-account :new-keypair]
dissoc
:seed-phrase
:random-phrase))
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]}))
(rf/reg-event-fx :wallet/new-keypair-created new-keypair-created)
(rf/reg-event-fx :wallet/store-account-generated store-account-generated)
(defn new-keypair-continue
(defn generate-account-for-keypair
[{:keys [db]} [{:keys [keypair-name]}]]
(let [seed-phrase (get-in db [:wallet :ui :create-account :seed-phrase])]
(let [seed-phrase (-> db :wallet :ui :create-account :new-keypair :seed-phrase)]
{:fx [[:effects.wallet/create-account-from-mnemonic
{:seed-phrase (security/safe-unmask-data seed-phrase)
:keypair-name keypair-name}]]}))
{:mnemonic-phrase (security/safe-unmask-data seed-phrase)
:paths [constants/path-default-wallet]
:on-success (fn [new-account-data]
(rf/dispatch [:wallet/store-account-generated
{:new-account-data new-account-data
:keypair-name keypair-name}]))}]]}))
(rf/reg-event-fx :wallet/new-keypair-continue new-keypair-continue)
(rf/reg-event-fx :wallet/generate-account-for-keypair generate-account-for-keypair)
(defn clear-new-keypair
(defn clear-create-account-data
[{:keys [db]}]
{:db (update-in db [:wallet :ui :create-account] dissoc :new-keypair)})
(rf/reg-event-fx :wallet/clear-new-keypair clear-new-keypair)
(rf/reg-event-fx :wallet/clear-create-account clear-create-account-data)
(defn get-derived-addresses
[{:keys [db]} [{:keys [password derived-from paths]}]]
@@ -80,6 +100,21 @@
(rf/reg-event-fx :wallet/get-derived-addresses get-derived-addresses)
(rf/reg-event-fx
:wallet/next-derivation-path
(fn [_ [{:keys [on-success keypair-uid]}]]
{:fx [[:json-rpc/call
[{:method "accounts_resolveSuggestedPathForKeypair"
:params [keypair-uid]
:on-success on-success
:on-error (fn [error]
(log/error
"Failed to resolve next path derivation path"
{:event :wallet/next-derivation-path
:method "accounts_resolveSuggestedPathForKeypair"
:error error
:params keypair-uid}))}]]]}))
(defn get-derived-addresses-success
[{:keys [db]} [response]]
(let [derived-address (first response)]
@@ -105,3 +140,53 @@
:wallet/clear-private-key-data
(fn [{:keys [db]} _]
{:db (update-in db [:wallet :ui :create-account] dissoc :private-key :public-address)}))
(rf/reg-event-fx
:wallet/create-keypair-with-account
(fn [{db :db} [password account-preferences]]
(let [{:keys [keypair-name
new-account-data]} (-> db :wallet :ui :create-account :new-keypair)
keypair-with-account (create-account.utils/prepare-new-account
{:keypair-name keypair-name
:account-data new-account-data
:account-preferences account-preferences})
new-address (some-> new-account-data
(create-account.utils/first-derived-account)
(:address)
(string/lower-case))
unmasked-password (security/safe-unmask-data password)]
{:fx [[:json-rpc/call
[{:method "accounts_addKeypair"
:params [unmasked-password keypair-with-account]
:on-success [:wallet/add-account-success new-address]
:on-error #(log/error "Failed to add Keypair and create account" %)}]]]})))
(defn import-and-create-keypair-with-account
[{db :db} [{:keys [password account-preferences]}]]
(let [account-data (-> db :wallet :ui :create-account :new-keypair :new-account-data)
unmasked-mnemonic (security/safe-unmask-data (:mnemonic account-data))
unmasked-password (security/safe-unmask-data password)]
{:fx [[:json-rpc/call
[{:method "accounts_importMnemonic"
:params [unmasked-mnemonic unmasked-password]
:on-success #(rf/dispatch
[:wallet/create-keypair-with-account password account-preferences])}]]]}))
(rf/reg-event-fx :wallet/import-and-create-keypair-with-account import-and-create-keypair-with-account)
(rf/reg-event-fx
:wallet/derive-address-and-add-account
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences]}]]
{:fx [[:json-rpc/call
[{:method "wallet_getDerivedAddresses"
:params [(security/safe-unmask-data password)
derived-from-address
[derivation-path]]
:on-success (fn [[derived-account]]
(rf/dispatch [:wallet/add-account
(assoc account-preferences :password password)
derived-account]))
:on-error #(log/info "Failed to get derived addresses"
derived-from-address
%)}]]]}))
@@ -1,8 +1,10 @@
(ns status-im.contexts.wallet.add-account.create-account.events-test
(:require
[cljs.test :refer-macros [deftest is]]
matcher-combinators.test
[status-im.contexts.wallet.add-account.create-account.events :as events]))
[matcher-combinators.test]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.events :as events]
[utils.security.core :as security]))
(deftest confirm-account-origin
(let [db {:wallet {:ui {:create-account {}}}}
@@ -15,32 +17,60 @@
(deftest store-seed-phrase
(let [db {}
props [{:seed-phrase "test-secret" :random-phrase "random-test"}]
expected-db {:wallet {:ui {:create-account {:seed-phrase "test-secret"
:random-phrase "random-test"}}}}
effects (events/store-seed-phrase {:db db} props)
expected-db {:wallet {:ui {:create-account {:new-keypair {:seed-phrase "test-secret"
:random-phrase "random-test"}}}}}
effects (events/store-new-seed-phrase {:db db} props)
result-db (:db effects)]
(is (match? result-db expected-db))))
(deftest new-keypair-created
(let [db {}
props [{:new-keypair "test-keypair"}]
expected-db {:wallet {:ui {:create-account {:new-keypair "test-keypair"}}}}
effects (events/new-keypair-created {:db db} props)
result-db (:db effects)]
(is (match? result-db expected-db))))
(deftest store-account-generated
(let [db {:wallet {:ui {:create-account
{:new-keypair {:seed-phrase "test-secret"
:random-phrase "random-test"}}}}}
mnemonic "my mnemonic"
masked-mnemonic (security/mask-data mnemonic)
props [{:new-account-data {"test" "data"
:mnemonic mnemonic}
:keypair-name "new-keypair-name"}]
expected-db {:wallet {:ui {:create-account
{:new-keypair
{:new-account-data {"test" "data"
:mnemonic masked-mnemonic}
:keypair-name "new-keypair-name"}}}}}
effects (events/store-account-generated {:db db} props)
result-db (:db effects)
remove-mnemonic #(update-in %
[:wallet :ui :create-account :new-keypair :new-account-data]
dissoc
:mnemonic)
unmask-mnemonic #(-> %
:wallet
:ui
:create-account
:new-keypair
:new-account-data
:mnemonic
security/safe-unmask-data)]
(is (= (remove-mnemonic result-db) (remove-mnemonic expected-db)))
(is (= (unmask-mnemonic result-db) (unmask-mnemonic expected-db)))))
(deftest new-keypair-continue
(let [db {:wallet {:ui {:create-account {:seed-phrase "test-secret"}}}}
(deftest generate-account-for-keypair
(let [db {:wallet {:ui {:create-account {:new-keypair {:seed-phrase "test-secret"}}}}}
props [{:keypair-name "test-keypair"}]
expected-effects [[:effects.wallet/create-account-from-mnemonic
{:seed-phrase "test-secret" :keypair-name "test-keypair"}]]
effects (events/new-keypair-continue {:db db} props)]
(is (match? effects {:fx expected-effects}))))
{:mnemonic-phrase "test-secret"
:paths [constants/path-default-wallet]}]]
effects (events/generate-account-for-keypair {:db db} props)]
(is (match?
(update-in effects [:fx 0 1] dissoc :on-success)
{:fx expected-effects}))
(is (some? (get-in effects [:fx 0 1 :on-success])))))
(deftest clear-new-keypair
(deftest clear-create-account-data
(let [db {:wallet {:ui {:create-account {:new-keypair "test-keypair"}}}}
expected-db {:wallet {:ui {:create-account {}}}}
effects (events/clear-new-keypair {:db db})]
effects (events/clear-create-account-data {:db db})]
(is (match? (:db effects) expected-db))))
(deftest get-derived-addresses-test
@@ -52,8 +52,8 @@
:import-private-key
(not-implemented/alert)
:new-key-pair
(rf/dispatch [:wallet/new-keypair-continue
:new-keypair
(rf/dispatch [:wallet/generate-account-for-keypair
{:keypair-name key-pair-name}])
(js/alert "Unknown workflow")))
[workflow key-pair-name])
@@ -108,7 +108,7 @@
:button-one-label (i18n/label :t/i-have-written)
:button-one-props {:disabled? (some false? (vals @checked?))
:customization-color customization-color
:on-press #(rf/dispatch [:wallet/store-seed-phrase
:on-press #(rf/dispatch [:wallet/store-new-seed-phrase
{:seed-phrase (security/mask-data
@seed-phrase)
:random-phrase @random-phrase}])}}]
@@ -65,7 +65,7 @@
quiz-index (reagent/atom 0)
incorrect-count (reagent/atom 0)
show-error? (reagent/atom false)
{:keys [seed-phrase random-phrase]} (rf/sub [:wallet/create-account])
{:keys [seed-phrase random-phrase]} (rf/sub [:wallet/create-account-new-keypair])
unmasked-seed-phrase (security/safe-unmask-data seed-phrase)]
(fn []
(let [current-word-index (get random-indices
@@ -82,7 +82,7 @@
(when (= @quiz-index questions-count)
(rf/dispatch [:navigate-to
:screen/wallet.keypair-name
{:workflow :new-key-pair}])))
{:workflow :new-keypair}])))
(do
(when (> @incorrect-count 0)
(rf/dispatch [:show-bottom-sheet
@@ -23,11 +23,11 @@
:add-divider? true
:on-press #(rf/dispatch [:navigate-to :screen/wallet.enter-seed-phrase
{:recovering-keypair? true}])}
{:icon :i/key
:accessibility-label :import-private-key
:label (i18n/label :t/import-private-key)
:on-press (when (ff/enabled? ::wallet.import-private-key)
#(rf/dispatch [:navigate-to :screen/wallet.import-private-key]))}]]])
(when (ff/enabled? ::wallet.import-private-key)
{:icon :i/key
:accessibility-label :import-private-key
:label (i18n/label :t/import-private-key)
:on-press #(rf/dispatch [:navigate-to :screen/wallet.import-private-key])})]]])
(defn- parse-accounts
[given-accounts]
@@ -1,19 +1,29 @@
(ns status-im.contexts.wallet.add-account.create-account.utils)
(ns status-im.contexts.wallet.add-account.create-account.utils
(:require [status-im.constants :as constants]))
(defn prepare-new-keypair
[{:keys [new-keypair address account-name account-color emoji derivation-path]}]
(assoc new-keypair
:name (:keypair-name new-keypair)
:key-uid (:keyUid new-keypair)
:type :seed
:derived-from address
:accounts [{:keypair-name (:keypair-name new-keypair)
:key-uid (:keyUid new-keypair)
:seed-phrase (:mnemonic new-keypair)
:public-key (:publicKey new-keypair)
:name account-name
:type :seed
:emoji emoji
:colorID account-color
:path derivation-path
:address (:address new-keypair)}]))
(defn first-derived-account
[account-data]
(-> account-data :derived first val))
(defn prepare-new-account
[{keypair-name :keypair-name
{:keys [keyUid address] :as account} :account-data
{:keys [account-name color emoji]} :account-preferences}]
(let [account-to-create (first-derived-account account)
account-config {:address (:address account-to-create)
:key-uid keyUid
:wallet false
:chat false
:type :seed
:path constants/path-default-wallet
:public-key (:publicKey account-to-create)
:name account-name
:emoji emoji
:colorID color
:hidden false}]
{:key-uid keyUid
:name keypair-name
:type :seed
:derived-from address
:last-used-derivation-index 0
:accounts [account-config]}))
@@ -12,14 +12,11 @@
[status-im.common.standard-authentication.core :as standard-auth]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.style :as style]
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.sheets.account-origin.view :as account-origin]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.responsiveness :as responsiveness]
[utils.security.core :as security]
[utils.string]))
(defn- get-keypair-data
@@ -57,107 +54,47 @@
:description :text
:description-props {:text formatted-path}}]))
(defn view
(defn- avatar
[{:keys [account-color emoji on-select-emoji]}]
[rn/view {:style style/account-avatar-container}
[quo/account-avatar
{:customization-color account-color
:size 80
:emoji emoji
:type :default}]
[quo/button
{:size 32
:type :grey
:background :photo
:icon-only? true
:on-press #(rf/dispatch [:emoji-picker/open {:on-select on-select-emoji}])
:container-style style/reaction-button-container}
:i/reaction]])
(defn- input
[_]
(let [top (safe-area/get-top)
bottom (safe-area/get-bottom)
{window-width :width} (rn/get-window)
account-color (reagent/atom (rand-nth colors/account-colors))
emoji (reagent/atom (emoji-picker.utils/random-emoji))
account-name (reagent/atom "")
on-change-text #(reset! account-name %)
show-account-origin #(rf/dispatch [:show-bottom-sheet
{:content account-origin/view}])]
(fn []
(let [theme (quo.theme/use-theme)
number-of-accounts (count (rf/sub
[:wallet/accounts-without-watched-accounts]))
{:keys [address customization-color]} (rf/sub [:profile/profile])
{:keys [new-keypair]} (rf/sub [:wallet/create-account])
keypairs (rf/sub [:wallet/keypairs])
selected-keypair-uid (rf/sub [:wallet/selected-keypair-uid])
placeholder (i18n/label :t/default-account-placeholder)
derivation-path (utils/get-derivation-path
number-of-accounts)
keypair (some #(when (= (:key-uid %) selected-keypair-uid)
%)
keypairs)
primary-keypair? (= selected-keypair-uid (:key-uid (first keypairs)))
create-new-keypair-account #(rf/dispatch
[:wallet/add-keypair-and-create-account
{:sha3-pwd (security/safe-unmask-data %)
:new-keypair
(create-account.utils/prepare-new-keypair
{:new-keypair new-keypair
:address address
:account-name @account-name
:account-color @account-color
:emoji @emoji
:derivation-path
derivation-path})}])
create-existing-keypair-account #(rf/dispatch [:wallet/derive-address-and-add-account
{:sha3-pwd (security/safe-unmask-data %)
:emoji @emoji
:color @account-color
:path derivation-path
:account-name @account-name}])
keypair-title (or (:keypair-name new-keypair)
(if primary-keypair?
(i18n/label :t/keypair-title
{:name (:name keypair)})
(:name keypair)))]
(rn/use-unmount #(rf/dispatch [:wallet/clear-new-keypair]))
[floating-button-page/view
{:gradient-cover? true
:footer-container-padding 0
:header-container-style {:padding-top top}
:customization-color @account-color
:header [quo/page-nav
{:type :no-title
:background :blur
:right-side [{:icon-name :i/info
:on-press show-account-origin}]
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
:footer [standard-auth/slide-button
{:size :size-48
:track-text (i18n/label :t/slide-to-create-account)
:customization-color @account-color
:on-auth-success (fn [password]
(if new-keypair
(create-new-keypair-account password)
(create-existing-keypair-account
password)))
:auth-button-label (i18n/label :t/confirm)
:disabled? (empty? @account-name)
:container-style (style/slide-button-container bottom)
:dependencies [new-keypair]}]}
[rn/view {:style style/account-avatar-container}
[quo/account-avatar
{:customization-color @account-color
:size 80
:emoji @emoji
:type :default}]
[quo/button
{:size 32
:type :grey
:background :photo
:icon-only? true
:on-press #(rf/dispatch [:emoji-picker/open
{:on-select (fn [selected-emoji]
(reset! emoji selected-emoji))}])
:container-style style/reaction-button-container}
:i/reaction]]
[quo/title-input
{:customization-color @account-color
:placeholder placeholder
:on-change-text on-change-text
:max-length constants/wallet-account-name-max-length
:blur? true
:disabled? false
:default-value @account-name
:container-style style/title-input-container}]
[quo/divider-line]
(let [placeholder (i18n/label :t/default-account-placeholder)]
(fn [{:keys [account-color account-name on-change-text]}]
[quo/title-input
{:customization-color account-color
:placeholder placeholder
:on-change-text on-change-text
:max-length constants/wallet-account-name-max-length
:blur? true
:disabled? false
:default-value account-name
:container-style style/title-input-container}])))
(defn- color-picker
[_]
(let [{window-width :width} (rn/get-window)
color-picker-style {:padding-vertical 12
:padding-left (responsiveness/iphone-11-Pro-20-pixel-from-width
window-width)}]
(fn [{:keys [account-color set-account-color]}]
[:<>
[quo/divider-line]
(let [theme (quo.theme/use-theme)]
[rn/view {:style style/color-picker-container}
[quo/text
{:size :paragraph-2
@@ -165,17 +102,168 @@
:style (style/color-label theme)}
(i18n/label :t/colour)]
[quo/color-picker
{:default-selected @account-color
:on-change #(reset! account-color %)
:container-style {:padding-vertical 12
:padding-left (responsiveness/iphone-11-Pro-20-pixel-from-width
window-width)}}]]
[quo/divider-line]
[quo/category
{:list-type :settings
:label (i18n/label :t/origin)
:data (get-keypair-data {:title keypair-title
:primary-keypair? primary-keypair?
:new-keypair? (boolean new-keypair)
:derivation-path derivation-path
:customization-color customization-color})}]]))))
{:default-selected account-color
:on-change set-account-color
:container-style color-picker-style}]])])))
(defn- new-account-origin
[{:keys [keypair-title derivation-path customization-color]}]
(let [{keypair-name :name} (rf/sub [:wallet/selected-keypair])
primary? (rf/sub [:wallet/selected-primary-keypair?])
keypair-name (or keypair-title
(if primary?
(i18n/label :t/keypair-title {:name keypair-name})
keypair-name))]
[:<>
[quo/divider-line]
[quo/category
{:list-type :settings
:label (i18n/label :t/origin)
:data (get-keypair-data {:primary-keypair? primary?
:title keypair-name
:derivation-path derivation-path
:customization-color customization-color})}]]))
(defn- floating-button
[_ & _]
(let [top (safe-area/get-top)
bottom (safe-area/get-bottom)
header [quo/page-nav
{:type :no-title
:background :blur
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content account-origin/view}])}]
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]]
(fn [{:keys [slide-button-props account-color]} & children]
(into
[floating-button-page/view
{:gradient-cover? true
:footer-container-padding 0
:header-container-style {:padding-top top}
:customization-color account-color
:header header
:footer [standard-auth/slide-button
(assoc slide-button-props
:size :size-48
:track-text (i18n/label :t/slide-to-create-account)
:customization-color account-color
:auth-button-label (i18n/label :t/confirm)
:container-style (style/slide-button-container bottom))]}]
children))))
(defn add-new-keypair-variant
[{:keys [on-change-text set-account-color set-emoji]
{:keys [account-name account-color emoji]}
:state}]
(let [on-auth-success (fn [password]
(rf/dispatch
[:wallet/import-and-create-keypair-with-account
{:password password
:account-preferences {:account-name @account-name
:color @account-color
:emoji @emoji}}]))]
(fn [{:keys [customization-color keypair-name]}]
(let [{:keys [new-account-data]} (rf/sub [:wallet/create-account-new-keypair])]
[floating-button
{:account-color @account-color
:slide-button-props {:on-auth-success on-auth-success
:disabled? (empty? @account-name)
:dependencies [new-account-data]}}
[avatar
{:account-color @account-color
:emoji @emoji
:on-select-emoji set-emoji}]
[input
{:account-color @account-color
:account-name @account-name
:on-change-text on-change-text}]
[color-picker
{:account-color @account-color
:set-account-color set-account-color}]
[new-account-origin
{:derivation-path constants/path-default-wallet
:customization-color customization-color
:keypair-title keypair-name}]]))))
(defn derive-account-variant
[{:keys [on-change-text set-account-color set-emoji]
{:keys [account-name account-color emoji]}
:state}]
(let [derivation-path (reagent/atom "")
set-derivation-path #(reset! derivation-path %)]
(fn [{:keys [customization-color]}]
(let [{:keys [derived-from
key-uid]} (rf/sub [:wallet/selected-keypair])
on-auth-success (rn/use-callback
(fn [password]
(let [preferences {:account-name @account-name
:color @account-color
:emoji @emoji}]
(rf/dispatch
[:wallet/derive-address-and-add-account
{:password password
:derived-from-address derived-from
:derivation-path @derivation-path
:account-preferences preferences}])))
[derived-from])]
(rn/use-effect
#(rf/dispatch
[:wallet/next-derivation-path
{:on-success set-derivation-path
:keypair-uid key-uid}])
[key-uid])
[floating-button
{:account-color @account-color
:slide-button-props {:on-auth-success on-auth-success
:disabled? (or (empty? @account-name)
(= "" @derivation-path))}}
[avatar
{:account-color @account-color
:emoji @emoji
:on-select-emoji set-emoji}]
[input
{:account-color @account-color
:account-name @account-name
:on-change-text on-change-text}]
[color-picker
{:account-color @account-color
:set-account-color set-account-color}]
[new-account-origin
{:derivation-path @derivation-path
:customization-color customization-color}]]))))
(defn view
[_]
(let [account-name (reagent/atom "")
account-color (reagent/atom (rand-nth colors/account-colors))
emoji (reagent/atom (emoji-picker.utils/random-emoji))
on-change-text #(reset! account-name %)
set-account-color #(reset! account-color %)
set-emoji #(reset! emoji %)
state {:account-name account-name
:account-color account-color
:emoji emoji}]
(fn []
(let [customization-color (rf/sub [:profile/customization-color])
;; Having a keypair means the user is importing it or creating it.
{:keys [keypair-name]} (rf/sub [:wallet/create-account-new-keypair])]
(rn/use-unmount #(rf/dispatch [:wallet/clear-create-account]))
(if keypair-name
[add-new-keypair-variant
{:customization-color customization-color
:on-change-text on-change-text
:set-account-color set-account-color
:set-emoji set-emoji
:state state
:keypair-name keypair-name}]
[derive-account-variant
{:customization-color customization-color
:on-change-text on-change-text
:set-account-color set-account-color
:set-emoji set-emoji
:state state}])))))
@@ -11,7 +11,7 @@
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:current-screen-id :screen/wallet.bridge-input-amount
:button-one-label (i18n/label :t/confirm-bridge)
:button-one-label (i18n/label :t/review-bridge)
:button-one-props {:icon-left :i/bridge}
:on-navigate-back (fn []
(rf/dispatch [:wallet/clean-disabled-from-networks])
@@ -1,7 +1,8 @@
(ns status-im.contexts.wallet.collectible.utils
(:require [status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]))
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[taoensso.timbre :as log]))
(defn collectible-balance
[collectible]
@@ -23,7 +24,7 @@
(if (supported-collectible-types collectible-type)
true
(do
(println "unsupoorted collectible file type" collectible-type)
(log/debug "unsupported collectible file type:" (or collectible-type "Unknown type"))
false)))
(defn total-owned-collectible
@@ -4,3 +4,7 @@
(def list-container-style
{:margin-horizontal 12
:padding-bottom constants/floating-shell-button-height})
(def collectible-container
{:padding 8
:flex 0.5})
@@ -9,10 +9,14 @@
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
[utils.i18n :as i18n]))
(defn- render-fn
[{:keys [preview-url collection-data ownership collectible-data] :as collectible} index address
on-press on-long-press]
(let [total-owned (utils/total-owned-collectible ownership address)]
(defn- collectible-item
[{:keys [preview-url collection-data collectible-data total-owned on-press on-long-press]
:as collectible}
index]
(let [on-press-fn (rn/use-callback #(when on-press
(on-press collectible)))
on-long-press-fn (rn/use-callback #(when on-long-press
(on-long-press collectible)))]
[quo/collectible-list-item
{:type :card
:image-src (:uri preview-url)
@@ -21,18 +25,15 @@
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
:gradient-color-index (keyword (str "gradient-" (inc (mod index 5))))
:counter (utils/collectible-owned-counter total-owned)
:container-style {:padding 8
:width "50%"}
:on-press #(when on-press
(on-press collectible))
:on-long-press #(when on-long-press
(on-long-press collectible))}]))
:container-style style/collectible-container
:on-press on-press-fn
:on-long-press on-long-press-fn}]))
(defn view
[{:keys [collectibles filtered? on-collectible-press on-end-reached current-account-address
on-collectible-long-press]}]
(let [no-results-match-query? (and filtered? (empty? collectibles))
theme (quo.theme/use-theme)]
[{:keys [collectibles filtered? on-end-reached
on-collectible-press current-account-address on-collectible-long-press]}]
(let [theme (quo.theme/use-theme)
no-results-match-query? (and filtered? (empty? collectibles))]
(cond
no-results-match-query?
[rn/view {:style {:flex 1 :justify-content :center}}
@@ -48,17 +49,25 @@
:image (resources/get-themed-image :no-collectibles theme)}]
:else
[rn/flat-list
{:data collectibles
:style {:flex 1}
:content-container-style style/list-container-style
:window-size 11
:num-columns 2
:render-fn (fn [item index]
(render-fn item
index
current-account-address
on-collectible-press
on-collectible-long-press))
:on-end-reached on-end-reached
:on-end-reached-threshold 4}])))
;; TODO: https://github.com/status-im/status-mobile/issues/20137
;; 1. If possible, move `collectibles-data` calculation to a subscription
;; 2. Optimization: do not recalculate all the collectibles, process only the new ones
(let [collectibles-data (map-indexed (fn [index {:keys [ownership] :as collectible}]
(assoc collectible
:total-owned (utils/total-owned-collectible
ownership
current-account-address)
:on-long-press on-collectible-long-press
:on-press on-collectible-press
:collectible-index index))
collectibles)]
[rn/flat-list
{:data collectibles-data
:style {:flex 1}
:content-container-style style/list-container-style
:window-size 11
:num-columns 2
:render-fn collectible-item
:on-end-reached on-end-reached
:key-fn :collectible-index
:on-end-reached-threshold 4}]))))
@@ -1,43 +0,0 @@
(ns status-im.contexts.wallet.common.temp
(:require
[react-native.core :as rn]
[status-im.common.resources :as status.resources]
[utils.i18n :as i18n]))
(def buy-tokens-list
[{:title "Ramp"
:description :text
:description-props {:text (i18n/label :t/ramp-description)}
:tag :context
:tag-props {:icon :i/fees
:context "0.49% - 2.9%"}
:action :arrow
:action-props {:alignment :flex-start
:icon :i/external}
:image :icon-avatar
:image-props {:icon (status.resources/get-service-image :ramp)}
:on-press #(rn/open-url "https://ramp.com")}
{:title "MoonPay"
:description :text
:description-props {:text (i18n/label :t/moonpay-description)}
:tag :context
:tag-props {:icon :i/fees
:context "1% - 4.5%"}
:action :arrow
:action-props {:alignment :flex-start
:icon :i/external}
:image :icon-avatar
:image-props {:icon (status.resources/get-service-image :moonpay)}
:on-press #(rn/open-url "https://moonpay.com")}
{:title "Latamex"
:description :text
:description-props {:text (i18n/label :t/latamex-description)}
:tag :context
:tag-props {:icon :i/fees
:context "1% - 1.7%"}
:action :arrow
:action-props {:alignment :flex-start
:icon :i/external}
:image :icon-avatar
:image-props {:icon (status.resources/get-service-image :latamex)}
:on-press #(rn/open-url "https://latamex.com")}])
@@ -42,6 +42,7 @@
(update :prod-preferred-chain-ids chain-ids-string->set)
(update :test-preferred-chain-ids chain-ids-string->set)
(update :type keyword)
(update :operable keyword)
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))
(update :emoji sanitize-emoji)
(assoc :default-account? (:wallet account))

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