Compare commits

...
Author SHA1 Message Date
Lungu Cristian 6215acdd23 feat: dismiss handler for modals 2024-07-22 13:10:51 +03:00
Icaro Motta cec46f985a chore(style): Sort JSON keys in translations/en.json (#20785)
Sorts keys (non-recursively) in translations/en.json. The solution uses
the prettier plugin https://github.com/Gudahtt/prettier-plugin-sort-json.

We only format translations/en.json because it’s the only file we need to
manually change.

- Dependency added: prettier-plugin-sort-json version 4.0.0
- Dependency upgraded: prettier, from version 2.8.8 to 3.3.3.
2024-07-21 22:39:50 -03:00
Volodymyr Kozieiev 06b2996167 Do not update disabled networks when receiver network updated (#20756) 2024-07-19 15:10:13 +01:00
Lungu Cristian 02e24208db Wallet Connect transactions (#20755)
* feat: updated signing endpoints and refactor

https://github.com/status-im/status-go/compare/6e056348...e8aec741

* fix: using the generic warning at the bottom

* fix: show parsed transaction parameters

* feat: adding fees to transactions

https://github.com/status-im/status-go/compare/6e056348...b2e5e7a8

* feat: added fees

* feat: added eip-1559 fee estimation & tx priority

* feat: added fees and failed processing handling

* fix: show testnet name in the request

* fix: address review comments

* feat: added max-fee color when not enough balance

* ref: broke down tx fees subscription

* fix: handle gas estimation on status-go

https://github.com/status-im/status-go/compare/1ef2434b...5389f281

* fix: don't overwrite dynamic fees if already there

* fix: malli schema and review comments

* fix: addressed review comments 1

* fix: addressed comments 2

* fix: removed unused require

* fix: addressed QA review

https://github.com/status-im/status-go/compare/484b8aca...d07f9b5b

* fix: requests being shown simultaneously

* fix: removed support for eth_signTransaction
2024-07-19 14:16:51 +03:00
frank 84b8943fd4 fix_:still return the image when image server is unable to get public key (#20538)
https://github.com/status-im/status-go/compare/cba3ac57...4a43b2b2
2024-07-19 17:17:53 +08:00
Ajay Sivan c52b3e457e Wallet/Swap Input Component (#20318) 2024-07-19 01:00:38 -07:00
Omar Basem 21cc8a199a fix: button width (#20792)
* fix: button width (#20792)
2024-07-19 08:13:50 +04:00
Yevheniia Berdnyk 59374543ef e2e: disabled activity verification in wallet tests 2024-07-18 19:45:20 +03:00
Alexander 9f84a7b912 A pack of bugfixes for the user story "Connect to dApps" (#20711) 2024-07-18 14:57:53 +02:00
Vit∀ly Vlasov 2b0847ef76 fix_: ui part for share-all-future-addresses storage (PR #20549) (#20549)
Related status-go PR: https://github.com/status-im/status-go/pull/5354

https://github.com/status-im/status-go/compare/6e056348...8458cafe

Signed-off-by: Vitaly Vlasov <mail@vitv.ly>
2024-07-18 15:36:38 +03:00
Yevheniia Berdnyk 97b19c5440 e2e: fixes for wallet and deep/universal links tests 2024-07-18 00:52:06 +03:00
Icaro Motta b3e88508ac chore(activity-center): Various small refactors (#20690)
Potentially a solution to https://github.com/status-im/status-mobile/issues/15706

- [x] Fixes swipe button on Android and iOS.
- [x] Performance: we now subscribe only to the minimum from each community.
      This could be the reason the AC would lag as described in the parent
      issue.
- [x] Performance: was able to use flex and removed swipe button height
      calculation that was using `onLayout` and was causing a re-render.
- [x] Performance: reduced the initial number of items to render in the flatlist
      from 10 to 7.
- [x] Performance: delay rendering the heavy list of notification components.
      See in the video below how slow it is to open the AC with just 6
      notifications and that the opening animation is never displayed. And then
      check the improved version with the artificial delay provided by
      `rn/delay-render`. By opening the AC first and animating, this gives the
      user something to look for, and hopefully a few milliseconds more to think
      the app is not stuck, which will be preciously used to render
      notifications.

We refactor all views in the AC to:

- [x] Follow our newest standards with React hooks.
- [x] Removed prop-drilling by creating a separate React context to store the
      current swipeable item (because we need to call `.close` on a `Gesture
      Swipeable` instance whenever a new swipeable opens.
2024-07-17 12:16:06 -03:00
Mohsen 7b09402fcb [#20742] fix: blue background behind the "Save address" button (#20754) 2024-07-17 16:04:40 +03:30
mmilad75 a912125ba9 Token value shows fiat value on the transaction confirmation page #20734 (#20770) 2024-07-17 10:47:27 +02:00
Ulises Manuel 2d0437dd5e fix(wallet): Improvements on activity tab (#20703)
* Fix schema for networks in context-tags

* Fix wallet-activity component overflowing the activity tab

* Improve robustness of the activity tab fetching mechanism

* Handle `wallet-activity-filtering-entries-updated` signal

* Improve processing of data received for the activity tab
2024-07-16 15:07:33 -06:00
Parvesh Monu 43651ef0d0 Adjust on-boarding illustrations position and scale (#20692) 2024-07-16 20:43:19 +05:30
Yevheniia Berdnyk 13232dc7b7 e2e: updated create profile flow 2024-07-16 15:46:23 +01:00
Andrea Maria Piana 93b5f7a918 Add confirmation to centralized metrics
This commit add a confirmation for centralized metrics.
It is added in 3 places:

1) Onboarding -> Create new account
2) Onboarding -> Sync profile
3) On the accounts view if the user is upgrading

To test 1 & 2, you should just be able to do that on a newly installed
device.

To test 3, you will have to upgrade from a PR without this feature that
has at least an account. It should show the confirmation modal until you
either click on Not now or Share usage data.

The modal should also be added in settings, but I will do that as a
separate PR.
2024-07-16 15:46:23 +01:00
Mohsen 4898d32243 [#20664] feat: add share usage data confirmation modal 2024-07-16 15:46:23 +01:00
Lungu Cristian 588692e0eb Wallet Connect message signing (#20693)
* feat: updated signing endpoints and refactor

https://github.com/status-im/status-go/compare/6e056348...e8aec741

* fix: address review comments
2024-07-16 14:36:16 +03:00
Nikolay bd9e440839 [18942] Slideshow: slider-bar component (#20615) 2024-07-16 12:42:38 +02:00
Ulises Manuel 940edc2e53 fix(wallet): Some collectibles were displayed as "can iOS can't fetch collectible error (#20714) 2024-07-15 12:34:02 -06:00
mmilad75 5a93cd755e Cover wallet send events with tests #20411 (#20533) 2024-07-15 14:56:50 +02:00
Yevheniia Berdnyk 942c130d23 e2e: separated tests to run in PRs 2024-07-15 12:46:18 +03:00
Andrea Maria Piana bb8aad3be8 set fleet to status.staging
https://github.com/status-im/status-go/compare/1ef2434b...484b8aca
2024-07-15 10:30:01 +01:00
Andrea Maria Piana ba76b9fd51 Allow setting store confirmations
This commit adds the ability to enable store confirmations in the UI,
under advanced settings.

https://github.com/status-im/status-go/compare/1ef2434b...0d1e5aae
2024-07-15 07:46:13 +01:00
142 changed files with 5835 additions and 4167 deletions
-1
View File
@@ -4,7 +4,6 @@ DEFAULT_NETWORK=mainnet_rpc
DEV_BUILD=1
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
+1 -1
View File
@@ -2,7 +2,7 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
FLEET=status.staging
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=0
-1
View File
@@ -3,7 +3,6 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=1
-1
View File
@@ -2,7 +2,6 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
-1
View File
@@ -2,7 +2,6 @@ DEBUG_WEBVIEW=0
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=
MAILSERVER_CONFIRMATIONS_ENABLED=1
+14 -9
View File
@@ -1,10 +1,15 @@
*
/*
# Format top-level js files.
!*.js
!*/
*.clj-kondo
*.shadow-cljs
modules
result
target
component-spec
/app
# Ignore all except src/js/**/*.js
!/src/
/src/*
!/src/js
!/src/js/**/*.js
# Ignore all except translations/en.json
!/translations/
/translations/*
!/translations/en.json
+4
View File
@@ -6,4 +6,8 @@ module.exports = {
tabWidth: 2,
trailingComma: 'all',
useTabs: false,
// JSON sorting
jsonSortOrder: '{ "/.*/": "caseInsensitiveLexical" } ',
plugins: ['prettier-plugin-sort-json'],
};
+1 -1
View File
@@ -317,7 +317,7 @@ lint: ##@test Run code style checks
scripts/lint/translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \
node_modules/.bin/prettier --write .
node_modules/.bin/prettier --check .
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
lint-fix: export TARGET := clojure
+1 -1
View File
@@ -99,7 +99,7 @@ pipeline {
--rerun_count=2 \
--testrail_report=True \
-m testrail_id \
-m \"new_ui_critical or new_ui_medium\" \
-m \"nightly\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_URL ?: apk_path}
"""
+1 -3
View File
@@ -35,13 +35,11 @@ pipeline {
description: 'OBSOLETE ARGUMENT TO BE REMOVED',
defaultValue: 'DUMMY',
)
/* Commented to use TEST_MARKERS values from job params
string(
name: 'TEST_MARKERS',
description: 'Marker expression for matching tests to run.',
defaultValue: 'new_ui_critical',
defaultValue: 'smoke',
)
*/
}
options {
+2 -2
View File
@@ -915,7 +915,7 @@ PODS:
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- react-native-compat (2.12.2):
- react-native-compat (2.11.2):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
@@ -1517,7 +1517,7 @@ SPEC CHECKSUMS:
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: 799045500f56146afc46245148080e7b7623cb75
react-native-cameraroll: af8eec1e585d053ff485d98ec837f9a8a11b5745
react-native-compat: 84e00e8dcff9251278c0d48f2bce81f4502e3925
react-native-compat: 3af9add14d349701306d3d052638435f6795ac2c
react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
react-native-hole-view: 6935448993bac79f2b5a4ad7e9741094cf810679
+2 -1
View File
@@ -97,7 +97,8 @@
"jest-silent-reporter": "^0.5.0",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
"prettier": "^2.8.8",
"prettier": "^3.3.3",
"prettier-plugin-sort-json": "^4.0.0",
"process": "0.11.10",
"react-test-renderer": "18.1.0",
"shadow-cljs": "2.26.2",
@@ -18,6 +18,7 @@
[{:keys [current-log-level
telemetry-enabled?
light-client-enabled?
store-confirmations-enabled?
current-fleet
test-networks-enabled?
is-goerli-enabled?
@@ -77,6 +78,15 @@
[:wakuv2.ui/toggle-light-client (not light-client-enabled?)])
:accessory :switch
:active light-client-enabled?}
{:size :small
:title (i18n/label :t/store-confirmations)
:accessibility-label :store-confirmations
:container-margin-bottom 8
:on-press
#(re-frame/dispatch
[:wakuv2.ui/toggle-store-confirmations (not store-confirmations-enabled?)])
:accessory :switch
:active store-confirmations-enabled?}
{:size :small
:title "Testnet mode"
:accessibility-label :test-networks-enabled
@@ -114,13 +124,14 @@
(views/defview advanced-settings
[]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
telemetry-enabled? [:profile/telemetry-enabled?]
current-log-level [:log-level/current-log-level]
current-fleet [:fleets/current-fleet]
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
store-confirmations-enabled? [:profile/store-confirmations-enabled?]
telemetry-enabled? [:profile/telemetry-enabled?]
current-log-level [:log-level/current-log-level]
current-fleet [:fleets/current-fleet]
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
[:<>
[quo/page-nav
{:type :title
@@ -130,13 +141,14 @@
:on-press #(rf/dispatch [:navigate-back])}]
[list/flat-list
{:data (flat-list-data
{:current-log-level current-log-level
:telemetry-enabled? telemetry-enabled?
:light-client-enabled? light-client-enabled?
:current-fleet current-fleet
:dev-mode? false
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
{:current-log-level current-log-level
:telemetry-enabled? telemetry-enabled?
:light-client-enabled? light-client-enabled?
:store-confirmations-enabled? store-confirmations-enabled?
:current-fleet current-fleet
:dev-mode? false
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
:key-fn (fn [_ i] (str i))
:render-fn render-item}]]))
-16
View File
@@ -1,16 +0,0 @@
(ns legacy.status-im.utils.hex
(:require
[clojure.string :as string]))
(defn normalize-hex
[hex]
(when hex
(string/lower-case (if (string/starts-with? hex "0x")
(subs hex 2)
hex))))
(defn valid-hex?
[hex]
(let [hex (normalize-hex hex)]
(and (re-matches #"^[0-9a-fA-F]+$" hex)
(not= (js/parseInt hex 16) 0))))
+16
View File
@@ -137,3 +137,19 @@
:on-error #(log/error "failed to set light client"
{:error %
:enabled? enabled?})}]})
(rf/defn toggle-store-confirmations
{:events [:wakuv2.ui/toggle-store-confirmations]}
[{:keys [db]} enabled?]
{:db (assoc-in db
[:profile/profile :wakuv2-config :EnableStoreConfirmationForMessagesSent]
enabled?)
:json-rpc/call [{:method "wakuext_setStoreConfirmationForMessagesSent"
:params [{:enabled enabled?}]
:on-success (fn []
(log/info "store confirmation set successfully" enabled?)
(re-frame/dispatch [:logout]))
:on-error #(log/error "failed to set store confirmation"
{:error %
:enabled? enabled?})}]})
@@ -1,5 +1,6 @@
(ns quo.components.avatars.token-avatar.view
(:require [quo.components.avatars.token-avatar.style :as style]
[quo.components.utilities.token.view :as token]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
@@ -12,13 +13,14 @@
[:map {:closed true}
[:type {:optional true} [:enum :asset :collectible]]
[:context? {:optional true} [:maybe :boolean]]
[:image :schema.common/image-source]
[:image {:optional true} [:maybe :schema.common/image-source]]
[:token {:optional true} [:maybe [:or :keyword :string]]]
[: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]}]
[{:keys [type context? image token network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :token-avatar}
@@ -32,9 +34,11 @@
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[rn/image
{:source image
:style (style/image type)}]]
[token/view
{:size :size-32
:token token
:style (style/image type)
:image-source image}]]
(when context?
[rn/image
{:source network-image
@@ -21,15 +21,17 @@
(colors/theme-colors colors/white colors/neutral-95 theme))})
(defn buttons-container
[actions]
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20})
[actions container-style]
(merge
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20}
container-style))
(def button-container
{:flex 1})
{:flex-grow 1})
(def description-top
{:flex-direction :row
@@ -30,7 +30,8 @@
[:button-two-props {:optional true} [:maybe :map]]
[:scroll? {:optional true} [:maybe :boolean]]
[:blur? {:optional true} [:maybe :boolean]]
[:container-style {:optional true} [:maybe :map]]]]]
[:container-style {:optional true} [:maybe :map]]
[:buttons-container-style {:optional true} [:maybe :map]]]]]
:any])
(def ^:private role-icon
@@ -42,7 +43,7 @@
(defn- view-internal
[{:keys [actions description description-text description-top-text error-message role button-one-label
button-two-label blur? button-one-props button-two-props scroll? container-style
context-tag-props]}]
buttons-container-style context-tag-props]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:style (merge (style/container scroll? blur? theme) container-style)}
@@ -72,14 +73,14 @@
:context (i18n/label (keyword "t" role))}
context-tag-props)]])
[rn/view {:style (style/buttons-container actions)}
[rn/view {:style (style/buttons-container actions buttons-container-style)}
(when (or (= actions :two-actions)
(= actions :two-vertical-actions))
[button/button
(merge
{:size 40
:background (when (or blur? scroll?) :blur)
:container-style style/button-container
:background (when (or blur? scroll?) :blur)
:theme theme
:accessibility-label :button-two}
button-two-props)
@@ -79,14 +79,20 @@
[counter-view counter])
[rn/view {:style (style/collectible-border theme)}]]]))
(defn invalid-image?
[image-src]
(or (nil? image-src)
(string/blank? image-src)))
(defn view-internal
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
on-collectible-load aspect-ratio gradient-color-index]
:or {gradient-color-index :gradient-1
on-collectible-load (fn [])}}]
(let [theme (quo.theme/use-theme)
[error? set-error] (rn/use-state (or (nil? image-src)
(string/blank? image-src)))]
[error? set-error] (rn/use-state (invalid-image? image-src))]
(rn/use-effect #(set-error (invalid-image? image-src))
[image-src])
[rn/pressable
{:style (merge container-style (style/container aspect-ratio))
:accessibility-label :expanded-collectible
@@ -121,6 +121,7 @@
[:card? {:optional true} [:maybe :boolean]]
[:right-icon {:optional true} [:maybe :keyword]]
[:right-content {:optional true} [:maybe :map]]
[:icon-color {:optional true} [:maybe :schema.common/customization-color]]
[:status {:optional true} [:maybe [:enum :default :loading]]]
[:subtitle-type {:optional true} [:maybe [:enum :default :icon :network :account :editable]]]
[:size {:optional true} [:maybe [:enum :default :small :large]]]
@@ -0,0 +1,25 @@
(ns quo.components.slideshow.slider-bar.component-spec
(:require
[quo.components.slideshow.slider-bar.view :as slider-bar]
[test-helpers.component :as h]))
(h/describe "Slideshow: slider-bar"
(h/test "default render"
(h/render-with-theme-provider [slider-bar/view {:accessibility-label :slider-bar}])
(h/is-truthy (h/query-by-label-text :slider-bar)))
(h/test "render with total-amount and active-index"
(h/render-with-theme-provider [slider-bar/view
{:total-amount 4
:active-index 1
:accessibility-label :slider-bar}])
(h/is-truthy (h/query-by-label-text :slider-bar))
(h/is-equal 4 (count (h/query-all-by-label-text :slide-bar-item))))
(h/test "render with total-amount active-index and possible scroll"
(h/render-with-theme-provider [slider-bar/view
{:total-amount 10
:active-index 7
:accessibility-label :slider-bar}])
(h/is-truthy (h/query-by-label-text :slider-bar))
(h/is-equal 10 (count (h/query-all-by-label-text :slide-bar-item)))))
@@ -0,0 +1,14 @@
(ns quo.components.slideshow.slider-bar.schema)
(def ?schema
[:=>
[:cat
[:map {:closed true}
[:total-amount {:optional true} [:maybe :int]]
[:active-index {:optional true} :int]
[:customization-color {:optional true}
[:maybe :schema.common/customization-color]]
[:blur? {:optional true} [:maybe :boolean]]
[:accessibility-label {:optional true} [:maybe :keyword]]
[:container-style {:optional true} [:maybe :map]]]]
:any])
@@ -0,0 +1,31 @@
(ns quo.components.slideshow.slider-bar.style
(:require
[quo.foundations.colors :as colors]))
(def list-wrapper
{:align-items :center})
(defn list-bar
[bar-width]
{:width bar-width})
(defn item-wrapper
[{:keys [size spacing]}]
{:width size
:height size
:margin-left spacing
:flex 1
:align-items :center
:justify-content :center})
(defn item
[{:keys [size spacing active? customization-color theme blur?]}]
{:width size
:height size
:border-radius spacing
:background-color
(cond
(and blur? active?) colors/white
(and blur? (not active?)) colors/white-opa-10
(and (not blur?) active?) (colors/resolve-color customization-color theme)
:else (colors/theme-colors colors/neutral-20 colors/neutral-80 theme))})
@@ -0,0 +1,150 @@
(ns quo.components.slideshow.slider-bar.view
(:require
[quo.components.slideshow.slider-bar.schema :as component-schema]
[quo.components.slideshow.slider-bar.style :as style]
[quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[schema.core :as schema]))
(def item-size 8)
(def item-spacing item-size)
(def max-length 6)
(def bar-width (* (+ item-spacing item-size) max-length))
(def micro-scale 0.25)
(def small-scale 0.5)
(def medium-scale 0.75)
(def default-scale 1)
(def items-before-scroll
(/ max-length 2))
(defn- calc-relative-index
"Calculates item index in visible area"
[index active-index total-length]
(let [last-index (dec total-length)]
(cond
(< active-index items-before-scroll) index
(> active-index
(- last-index items-before-scroll)) (+ (- index total-length) max-length)
:else (+ (- index active-index) items-before-scroll))))
(defn- calc-first-item-scale
"Calculates scale for first item in visible area"
[active-index]
(cond
(= active-index items-before-scroll) medium-scale
(> active-index items-before-scroll) small-scale
:else default-scale))
(defn- calc-second-item-scale
"Calculates scale for second item in visible area"
[active-index]
(if (> active-index items-before-scroll)
medium-scale
default-scale))
(defn- calc-last-item-scale
"Calculates scale for last item in visible area"
[active-index total-length]
(let [last-index (dec total-length)]
(if (> active-index (- last-index items-before-scroll))
medium-scale
small-scale)))
(defn- calc-last-but-one-item-scale
"Calculates scale for before last item in visible area"
[active-index total-length]
(if (> active-index (- (dec total-length) items-before-scroll))
default-scale
medium-scale))
(defn- get-scale
[index active-index total-length]
(let [relative-index (calc-relative-index index active-index total-length)]
(if (or (= index active-index)
(< total-length max-length))
default-scale
(cond
(< relative-index 0) micro-scale
(= relative-index 0) (calc-first-item-scale active-index)
(= relative-index 1) (calc-second-item-scale active-index)
(= relative-index 4) (calc-last-but-one-item-scale active-index total-length)
(= relative-index 5) (calc-last-item-scale active-index total-length)
(> relative-index 5) micro-scale
:else
default-scale))))
(defn- bar-item
[index _ _ {:keys [active-index total-length customization-color theme blur?]}]
(let [active? (= index active-index)
shared-scale (reanimated/use-shared-value (get-scale index active-index total-length))]
(rn/use-effect (fn []
(let [new-scale-value (get-scale index active-index total-length)]
(reanimated/animate shared-scale new-scale-value)))
[index active-index total-length])
[rn/view
{:key index
:style (style/item-wrapper {:size item-size
:spacing item-spacing})}
[reanimated/view
{:accessibility-label :slide-bar-item
:style
(reanimated/apply-animations-to-style
{:transform [{:scale shared-scale}]}
(style/item {:size item-size
:spacing item-spacing
:active? active?
:customization-color customization-color
:theme theme
:blur? blur?}))}]]))
(defn- get-item-layout
[_ index]
(let [length (+ item-size item-spacing)]
#js {:length length
:index index
:offset (* index length)}))
(defn- view-internal
[{:keys [customization-color blur? accessibility-label container-style]
:as props}]
(let [active-index (or (:active-index props) 0)
total-amount (or (:total-amount props) 1)
theme (quo.theme/use-theme)
flat-list-ref (rn/use-ref-atom nil)
set-flat-list-ref (rn/use-callback #(reset! flat-list-ref %))
center-position 0.5
data (range total-amount)
scroll-to-index (rn/use-callback
(fn []
(some-> ^js @flat-list-ref
(.scrollToIndex #js {:animated true
:index active-index
:viewOffset item-spacing
:viewPosition center-position})))
[flat-list-ref active-index])]
(rn/use-effect scroll-to-index [active-index])
[rn/view
{:style (merge style/list-wrapper container-style)
:accessibility-label accessibility-label}
[reanimated/flat-list
{:style (style/list-bar bar-width)
:data data
:scroll-enabled false
:ref set-flat-list-ref
:shows-horizontal-scroll-indicator false
:bounces false
:horizontal true
:extra-data (str active-index)
:render-data {:active-index active-index
:total-length total-amount
:customization-color customization-color
:theme theme
:blur? blur?}
:get-item-layout get-item-layout
:render-fn bar-item
:key-fn identity}]]))
(def view (schema/instrument #'view-internal component-schema/?schema))
@@ -53,7 +53,7 @@
(def ^:private ?network
[:map
[:network-logo {:optional true} [:maybe :schema.common/image-source]]
[:network-name {:optional true} [:maybe :string]]])
[:network-name {:optional true} [:maybe [:or :string :keyword]]]])
(def ^:private ?multinetwork
[:map
@@ -41,7 +41,8 @@
:align-items :center
:height size
:background-color background-color
:border-radius border-radius}
:border-radius border-radius
:flex-shrink 1}
(= state :selected) (assoc :height (+ size 2)
:border-color border-color
:border-width 1))))
@@ -50,11 +51,13 @@
[size]
{:margin-right (if (= size 24) 6 10)
:flex-direction :row
:flex-shrink 1
:align-items :center})
(defn tag-spacing
[size]
{:margin-left (if (= size 24) 4 8)})
[size shrinkable?]
(cond-> {:margin-left (if (= size 24) 4 8)}
shrinkable? (assoc :flex-shrink 1)))
(defn text
[theme]
+12 -9
View File
@@ -17,17 +17,19 @@
[schema.core :as schema]))
(defn- tag-skeleton
[{:keys [size text theme]
[{:keys [size text theme shrinkable?]
:or {size 24
theme (quo.theme/use-theme)}}
logo-component]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[rn/view {:style (style/tag-spacing size shrinkable?)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)
:number-of-lines 1
:ellipsize-mode :middle}
text]]])
(defn- communities-tag
@@ -37,7 +39,7 @@
icon-size (if (= size 24) 16 20)]
[rn/view {:style (style/tag-container size)}
[fast-image/fast-image {:style (style/circle-logo size) :source community-logo}]
[rn/view {:style (style/tag-spacing size)}
[rn/view {:style (style/tag-spacing size false)}
[text/text
{:style (style/text theme)
:weight :medium
@@ -148,9 +150,10 @@
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)
:shrinkable? true}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:account
@@ -0,0 +1,31 @@
(ns quo.components.wallet.swap-input.component-spec
(:require [quo.components.wallet.swap-input.view :as swap-input]
[test-helpers.component :as h]))
(h/describe "Wallet: Swap Input"
(h/test "should render correctly with props"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:error? false
:token "SNT"
:status :default
:currency-symbol "€"
:value "5"
:fiat-value "1.50"
:network-tag-props {:title "Max: 200 SNT"}}])
(h/is-truthy (h/get-by-label-text :swap-input))
(h/is-truthy (h/get-by-text "SNT"))
(h/is-truthy (h/get-by-text "€1.50"))
(h/is-truthy (h/get-by-text "Max: 200 SNT")))
(h/test "should render correctly with approval label"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:show-approval-label? true
:approval-label-props
{:status :approve
:token-value "10"
:token-symbol "SNT"}}])
(h/is-truthy (h/get-by-text "Approve 10 SNT"))))
@@ -0,0 +1,74 @@
(ns quo.components.wallet.swap-input.style
(:require [quo.foundations.colors :as colors]
[quo.foundations.typography :as typography]))
(defn- border-color
[theme]
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))
(defn- loader-color
[theme]
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))
(defn content
[theme]
{:border-width 1
:border-radius 16
:border-color (border-color theme)
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
(defn row-1
[loading?]
{:padding 12
:gap 8
:align-items (if loading? :center :flex-end)
:flex-direction :row})
(defn row-1-loader
[theme]
{:width 74
:height 14
:border-radius 6
:background-color (loader-color theme)})
(def input-container
{:flex 1
:flex-direction :row
:gap 5
:height 32
:align-items :flex-end})
(defn input
[disabled? error? theme]
(assoc typography/font-semi-bold
:font-size 27
:flex-shrink 1
:padding 0
:color (cond
error? (colors/resolve-color :danger theme)
disabled? (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:else (colors/theme-colors colors/neutral-100 colors/white theme))
:line-height 32))
(defn token-symbol
[theme]
{:padding-bottom 3
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(defn row-2
[align-right?]
{:flex-direction :row
:justify-content (if align-right? :flex-end :space-between)
:align-items :center
:padding 12})
(defn row-2-loader
[theme]
{:width 80
:height 10
:margin-vertical 7
:border-radius 6
:background-color (loader-color theme)})
(def fiat-amount
{:color colors/neutral-50})
@@ -0,0 +1,121 @@
(ns quo.components.wallet.swap-input.view
(:require [oops.core :as oops]
[quo.components.avatars.token-avatar.view :as token-avatar]
[quo.components.buttons.button.view :as buttons]
[quo.components.dividers.divider-line.view :as divider-line]
[quo.components.markdown.text :as text]
[quo.components.tags.network-tags.view :as network-tag]
[quo.components.wallet.approval-label.schema :as approval-label.schema]
[quo.components.wallet.approval-label.view :as approval-label]
[quo.components.wallet.swap-input.style :as style]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type {:optional true} [:maybe [:enum :pay :receive]]]
[:status {:optional true} [:maybe [:enum :default :disabled :loading]]]
[:token {:optional true} [:maybe :string]]
[:value {:optional true} [:maybe :string]]
[:default-value {:optional true} [:maybe :string]]
[:currency-symbol {:optional true} [:maybe :string]]
[:fiat-value {:optional true} [:maybe :string]]
[:show-approval-label? {:optional true} [:maybe :boolean]]
[:error? {:optional true} [:maybe :boolean]]
[:show-keyboard? {:optional true} [:maybe :boolean]]
[:approval-label-props {:optional true} [:maybe approval-label.schema/?schema]]
[:network-tag-props {:optional true} [:maybe :map]]
[:on-change-text {:optional true} [:maybe fn?]]
[:enable-swap? {:optional true} [:maybe :boolean]]
[:on-swap-press {:optional true} [:maybe fn?]]
[:on-token-press {:optional true} [:maybe fn?]]
[:on-max-press {:optional true} [:maybe fn?]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn view-internal
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
approval-label-props default-value enable-swap?
currency-symbol on-change-text show-keyboard?
container-style on-swap-press on-token-press on-max-press]}]
(let [theme (quo.theme/use-theme)
pay? (= type :pay)
disabled? (= status :disabled)
loading? (= status :loading)
controlled-input? (some? value)
input-ref (rn/use-ref-atom nil)
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)) [])
focus-input (rn/use-callback (fn []
(some-> @input-ref
(oops/ocall "focus")))
[input-ref])]
[rn/view
{:style container-style
:accessibility-label :swap-input}
[rn/view {:style (style/content theme)}
[rn/view
{:style (style/row-1 loading?)}
[rn/pressable {:on-press on-token-press}
[token-avatar/view
{:type :asset
:token token}]]
(if loading?
[rn/view {:style (style/row-1-loader theme)}]
[:<>
[rn/pressable
{:style style/input-container
:on-press focus-input}
[rn/text-input
(cond-> {:ref set-input-ref
:style (style/input disabled? error? theme)
:placeholder-text-color (colors/theme-colors colors/neutral-40
colors/neutral-50
theme)
:keyboard-type :numeric
:auto-focus true
:on-change-text on-change-text
:show-soft-input-on-focus show-keyboard?
:default-value default-value
:placeholder "0"}
controlled-input? (assoc :value value))]
[text/text
{:size :paragraph-2
:weight :semi-bold
:style (style/token-symbol theme)}
token]]
(when (and pay? enable-swap?)
[buttons/button
{:type :outline
:size 32
:on-press on-swap-press
:icon-only? true}
:i/reorder])])]
[divider-line/view]
[rn/view
{:style (style/row-2 (or (not pay?) loading?))}
(when-not loading?
[:<>
(when pay?
[rn/pressable {:on-press on-max-press}
[network-tag/view
(assoc network-tag-props
:status
(if error? :error :default))]])
[text/text
{:size :paragraph-2
:style style/fiat-amount
:weight :medium}
(str currency-symbol fiat-value)]])
(when loading?
[rn/view {:style (style/row-2-loader theme)}])]]
(when (and (not= status :loading) (= type :pay) show-approval-label?)
[approval-label/view
approval-label-props])]))
(def view (schema/instrument #'view-internal ?schema))
@@ -51,8 +51,7 @@
(defn prop-text
[theme]
{:margin-right 4
:color (colors/theme-colors colors/neutral-100 colors/white theme)})
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
(def icon-container
{:width 32
@@ -61,12 +60,15 @@
(def container
{:flex-direction :row
:flex 1
:column-gap 8})
(def content-line
{:flex-direction :row
:margin-top 2
:align-items :center})
{:flex-direction :row
:margin-top 2
:align-items :center
:column-gap 4
:justify-content :flex-start})
(def icon-hole-view
{:width 32
@@ -98,8 +98,11 @@
(defn prop-tag
[props blur?]
[rn/view {:style {:margin-right 4}}
[context-tag/view (merge props {:size 24 :blur? blur?})]])
[context-tag/view
(assoc props
:size 24
:blur? blur?
:container-style {:flex-shrink 1})])
(defn- view-internal
[{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press
@@ -121,7 +124,7 @@
:on-press-out on-press-out}
[rn/view {:style style/container}
[transaction-icon-view props theme]
[rn/view
[rn/view {:style {:flex 1}}
[transaction-header props theme]
[rn/view {:style style/content-line}
(when first-tag [prop-tag first-tag blur?])
+6
View File
@@ -147,6 +147,7 @@
quo.components.settings.settings-item.view
quo.components.share.qr-code.view
quo.components.share.share-qr-code.view
quo.components.slideshow.slider-bar.view
quo.components.switchers.group-messaging-card.view
quo.components.tabs.account-selector
quo.components.tabs.segmented-tab
@@ -185,6 +186,7 @@
quo.components.wallet.progress-bar.view
quo.components.wallet.required-tokens.view
quo.components.wallet.summary-info.view
quo.components.wallet.swap-input.view
quo.components.wallet.token-input.view
quo.components.wallet.transaction-progress.view
quo.components.wallet.transaction-summary.view
@@ -418,6 +420,9 @@
(def qr-code quo.components.share.qr-code.view/view)
(def share-qr-code quo.components.share.share-qr-code.view/view)
;;;; Slideshow
(def slider-bar quo.components.slideshow.slider-bar.view/view)
;;;; SWITCHER
(def group-messaging-card quo.components.switchers.group-messaging-card.view/view)
@@ -468,6 +473,7 @@
(def progress-bar quo.components.wallet.progress-bar.view/view)
(def required-tokens quo.components.wallet.required-tokens.view/view)
(def summary-info quo.components.wallet.summary-info.view/view)
(def swap-input quo.components.wallet.swap-input.view/view)
(def network-link quo.components.wallet.network-link.view/view)
(def token-input quo.components.wallet.token-input.view/view)
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
+2
View File
@@ -87,6 +87,7 @@
quo.components.settings.reorder-item.component-spec
quo.components.settings.settings-item.component-spec
quo.components.share.share-qr-code.component-spec
quo.components.slideshow.slider-bar.component-spec
quo.components.switchers.base-card.component-spec
quo.components.switchers.group-messaging-card.component-spec
quo.components.tags.collectible-tag.component-spec
@@ -111,6 +112,7 @@
quo.components.wallet.progress-bar.component-spec
quo.components.wallet.required-tokens.component-spec
quo.components.wallet.summary-info.component-spec
quo.components.wallet.swap-input.component-spec
quo.components.wallet.token-input.component-spec
quo.components.wallet.transaction-progress.component-spec
quo.components.wallet.transaction-summary.component-spec
@@ -48,7 +48,7 @@
set-animating-true #(reset! animating? true)
set-animating-false (fn [ms]
(js/setTimeout #(reset! animating? false) ms))]
(fn [{:keys [content skip-background?]}]
(fn [{:keys [content skip-background? on-dismiss]}]
(let [theme (quo.theme/use-theme)
{:keys [top] :as insets} (safe-area/get-insets)
alert-banners-top-margin (rf/sub [:alert-banners/top-margin])
@@ -63,6 +63,10 @@
(reanimated/animate opacity 0 300)
(rf/dispatch [:navigate-back])
true)
dismiss (fn []
(when on-dismiss
(on-dismiss))
(close))
reset-open-sheet (fn []
(reanimated/animate translate-y 0 300)
(reanimated/animate opacity 1 300)
@@ -83,7 +87,7 @@
:opacity opacity
:scroll-enabled? scroll-enabled?
:curr-scroll curr-scroll
:close close
:close dismiss
:reset-open-sheet reset-open-sheet
:set-animating-true set-animating-true})}
[reanimated/view {:style (style/main-view translate-y theme)}
@@ -1,5 +1,6 @@
(ns status-im.common.floating-button-page.floating-container.style
(:require [react-native.safe-area :as safe-area]))
(:require [quo.foundations.colors :as colors]
[react-native.safe-area :as safe-area]))
(defn content-container
[blur? keyboard-shown?]
@@ -11,7 +12,12 @@
:padding-horizontal 20}
blur? (dissoc :padding-vertical :padding-horizontal))))
(def blur-inner-container
{:background-color :transparent ; required, otherwise blur-view will shrink
(defn blur-inner-container
[theme shell-overlay?]
{:background-color (colors/theme-colors colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme)
:padding-vertical 12
:padding-horizontal 20})
@@ -1,27 +1,25 @@
(ns status-im.common.floating-button-page.floating-container.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.floating-container.style :as style]))
(defn- blur-container
[child]
[child shell-overlay?]
(let [theme (quo.theme/use-theme)]
[quo/blur
{:blur-amount 52
:blur-radius 20
:blur-type :transparent
:blur-overlay-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme)}
[rn/view {:style style/blur-inner-container}
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent}
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
child]]))
(defn view
[{:keys [on-layout keyboard-shown? blur?]} child]
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
[rn/view
{:style (style/content-container blur? keyboard-shown?)
:on-layout on-layout}
(if blur?
[blur-container child]
[blur-container child shell-overlay?]
child)])
@@ -58,7 +58,7 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
content-container-style gradient-cover? keyboard-should-persist-taps]
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@@ -121,7 +121,8 @@
[floating-container/view
{:on-layout set-footer-container-height
:keyboard-shown? keyboard-shown?
:blur? show-background?}
:blur? show-background?
:shell-overlay? shell-overlay?}
footer]]]])
(finally
(remove-listeners))))
@@ -0,0 +1,14 @@
(ns status-im.common.metrics-confirmation-modal.style)
(def points-wrapper
{:margin-top 11
:margin-horizontal 20
:gap 21
:margin-bottom 15})
(def item-text
{:margin-top 10
:margin-left -4})
(def info-text
{:margin-top -5})
@@ -0,0 +1,79 @@
(ns status-im.common.metrics-confirmation-modal.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.metrics-confirmation-modal.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- dismiss-keyboard
[]
(rf/dispatch [:dismiss-keyboard]))
(defn- hide-bottom-sheet
[]
(rf/dispatch [:hide-bottom-sheet]))
(defn- toggle-metrics
[enabled?]
(rf/dispatch [:centralized-metrics/toggle-centralized-metrics enabled?]))
(def ^:private will-receive-points
[:t/ip-address
:t/universally-unique-identifiers-of-device
:t/logs-of-actions-withing-the-app])
(def ^:private not-receive-points
[:t/your-profile-information
:t/your-addresses
:t/information-you-input-and-send])
(defn- bullet-points
[{:keys [title points]}]
[rn/view
[quo/text {:weight :semi-bold}
title]
(for [label points]
^{:key label}
[quo/markdown-list
{:description (i18n/label label)
:blur? true
:container-style style/item-text}])])
(defn- on-share-usage
[]
(toggle-metrics true)
(hide-bottom-sheet))
(defn- on-do-not-share
[]
(toggle-metrics false)
(hide-bottom-sheet))
(defn view
[{:keys [settings?]}]
(rn/use-mount #(dismiss-keyboard))
[:<>
[quo/drawer-top
{:title (i18n/label :t/help-us-improve-status)
:description (i18n/label :t/collecting-usage-data)}]
[rn/view {:style style/points-wrapper}
[bullet-points
{:title (i18n/label :t/what-we-will-receive)
:points will-receive-points}]
[bullet-points
{:title (i18n/label :t/what-we-wont-receive)
:points not-receive-points}]
(when-not settings?
[quo/text
{:size :paragraph-2
:style style/info-text}
(i18n/label :t/sharing-usage-data-can-be-turned-off)])]
[quo/bottom-actions
{:actions :two-actions
:blur? true
:button-one-label (i18n/label :t/share-usage-data)
:button-one-props {:on-press on-share-usage}
:button-two-label (i18n/label (if settings? :t/do-not-share :t/not-now))
:button-two-props {:type :grey
:on-press on-do-not-share}}]])
+1 -1
View File
@@ -72,7 +72,7 @@
;; CONFIG VALUES
(def log-level (string/upper-case (get-config :LOG_LEVEL "")))
(def fleet (get-config :FLEET "waku.sandbox"))
(def fleet (get-config :FLEET ""))
(def apn-topic (get-config :APN_TOPIC "im.status.ethereum"))
(def default-network (get-config :DEFAULT_NETWORK "goerli_rpc"))
(def max-installations 2)
+11 -1
View File
@@ -45,6 +45,11 @@
(def ^:const activity-center-membership-status-accepted 2)
(def ^:const activity-center-membership-status-declined 3)
;; Choose the maximum number of notifications that *usually/safely* fit on
;; most screens, so that the UI doesn't have to needlessly render
;; notifications.
(def ^:const notifications-per-page 7)
(def ^:const mute-for-15-mins-type 1)
(def ^:const mute-for-1-hour-type 2)
(def ^:const mute-for-8-hours-type 3)
@@ -276,12 +281,14 @@
#{wallet-connect-personal-sign-method
wallet-connect-eth-sign-method
wallet-connect-eth-send-transaction-method
wallet-connect-eth-sign-transaction-method
;; NOTE: disabled, as we have no clear use cases for it and other wallets don't support it
;; wallet-connect-eth-sign-transaction-method
wallet-connect-eth-sign-typed-method
wallet-connect-eth-sign-typed-v4-method})
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
(def ^:const wallet-connect-session-proposal-event "session_proposal")
(def ^:const wallet-connect-session-request-event "session_request")
(def ^:const wallet-connect-session-delete-event "session_delete")
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
@@ -506,6 +513,9 @@
(def ^:const optimism-full-name "Optimism")
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const sepolia-full-name "Sepolia")
(def ^:const goerli-full-name "Goerli")
(def ^:const mainnet-network-name :mainnet)
(def ^:const ethereum-network-name :ethereum)
(def ^:const optimism-network-name :optimism)
@@ -7,10 +7,17 @@
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(def ^:const user-confirmed-key :centralized-metrics/user-confirmed?)
(def ^:const enabled-key :centralized-metrics/enabled?)
(defn show-confirmation-modal?
[db]
(not (user-confirmed-key db)))
(defn push-event?
[db]
(or (not (:centralized-metrics/user-confirmed? db))
(:centralized-metrics/enabled? db)))
(or (not (user-confirmed-key db))
(enabled-key db)))
(defn centralized-metrics-interceptor
[context]
@@ -29,5 +36,16 @@
(fn [{:keys [db]} [enabled?]]
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
:db (assoc db
:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? enabled?)}))
user-confirmed-key
true
enabled-key
enabled?)}))
(rf/reg-event-fx :centralized-metrics/check-modal
(fn [{:keys [db]} [modal-view]]
(when (show-confirmation-modal? db)
{:fx [[:dispatch
[:show-bottom-sheet
{:content (fn [] [modal-view])
:shell? true}]]]})))
@@ -6,6 +6,11 @@
[status-im.contexts.centralized-metrics.tracking :as tracking]
[test-helpers.unit :as h]))
(deftest show-confirmation-modal-test
(testing "returns true if the user confirmed"
(is (false? (events/show-confirmation-modal? {events/user-confirmed-key true})))
(is (true? (events/show-confirmation-modal? {})))))
(deftest push-event-test
(testing "returns correct boolean value"
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
@@ -27,7 +27,7 @@
:on-error #(p-reject (str "failed to sign data\n" %))}))))
(defn- edit-shared-addresses-for-community
[community-id signatures addresses-to-reveal airdrop-address]
[community-id signatures addresses-to-reveal airdrop-address _share-future-addresses?]
(promesa/create
(fn [p-resolve p-reject]
(rpc/call
@@ -41,15 +41,16 @@
:on-error p-reject}))))
(defn- request-to-join
[community-id signatures addresses-to-reveal airdrop-address]
[community-id signatures addresses-to-reveal airdrop-address share-future-addresses?]
(promesa/create
(fn [p-resolve p-reject]
(rpc/call
{:method :wakuext_requestToJoinCommunity
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress airdrop-address}]
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress airdrop-address
:shareFutureAddresses share-future-addresses?}]
:js-response true
:on-success p-resolve
:on-error p-reject}))))
@@ -64,15 +65,18 @@
(defn- sign-and-call-endpoint
[{:keys [community-id password pub-key
addresses-to-reveal airdrop-address
addresses-to-reveal airdrop-address share-future-addresses?
on-success on-error
callback]}]
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key community-id addresses-to-reveal)
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key
community-id
addresses-to-reveal)
signatures (sign-data sign-params password)
result (callback community-id
signatures
addresses-to-reveal
airdrop-address)]
airdrop-address
share-future-addresses?)]
(run-callback-or-event on-success result))
(promesa/catch #(run-callback-or-event on-error %))))
@@ -87,6 +91,7 @@
[:or [:set string?]
[:sequential string?]]]
[:airdrop-address string?]
[:share-future-addresses? boolean?]
[:on-success [:or fn? :schema.re-frame/event]]
[:on-error [:or fn? :schema.re-frame/event]]
[:callback fn?]]]
@@ -17,13 +17,12 @@
(rf/reg-event-fx :communities/initialize-permission-addresses initialize-permission-addresses)
(defn do-init-permission-addresses
[{:keys [db]} [community-id revealed-accounts]]
[{:keys [db]} [community-id revealed-accounts share-future-addresses?]]
(let [wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq revealed-accounts)
(set (keys revealed-accounts))
;; Reveal all addresses as fallback.
(set (map :address wallet-accounts)))
;; When there are no revealed addresses, such as when joining a
;; community, use first address for airdrops.
airdrop-address (or (->> revealed-accounts
@@ -35,10 +34,7 @@
first
:address))]
{:db (-> db
;; Set to false by default while we don't persist the user's choice
;; in status-go, otherwise whenever the view is mounted, the choice
;; of selected addresses won't be respected.
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/selected-share-all-addresses community-id] share-future-addresses?)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
:fx [[:dispatch
@@ -60,36 +56,44 @@
is selecting an airdrop address, we must submit to status-go the current
choice of addresses to share, and vice-versa. If we omit addresses to share,
status-go will default to all available."
[{:keys [db]} [{:keys [community-id password on-success addresses airdrop-address]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq addresses)
(set addresses)
(get-in db [:communities/all-addresses-to-reveal community-id]))
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
airdrop-address
(->> wallet-accounts
(filter #(contains? addresses-to-reveal (:address %)))
first
:address))]
[{:keys [db]}
[{:keys [community-id password on-success addresses airdrop-address share-future-addresses?]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq addresses)
(set addresses)
(get-in db [:communities/all-addresses-to-reveal community-id]))
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
airdrop-address
(->> wallet-accounts
(filter #(contains? addresses-to-reveal (:address %)))
first
:address))
share-future-addresses? (if (nil? share-future-addresses?)
(get-in db [:communities/selected-share-all-addresses community-id])
share-future-addresses?)]
{:fx [[:effects.community/edit-shared-addresses
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address new-airdrop-address
:on-success (fn []
(when (fn? on-success)
(on-success addresses-to-reveal new-airdrop-address))
(rf/dispatch [:communities/edit-shared-addresses-success
community-id addresses-to-reveal airdrop-address]))
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:share-future-addresses? share-future-addresses?
:airdrop-address new-airdrop-address
:on-success (fn []
(when (fn? on-success)
(on-success addresses-to-reveal
new-airdrop-address
share-future-addresses?))
(rf/dispatch [:communities/edit-shared-addresses-success
community-id addresses-to-reveal airdrop-address]))
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
(rf/reg-event-fx :communities/edit-shared-addresses edit-shared-addresses)
(rf/reg-event-fx :communities/edit-shared-addresses-success
(fn [_ [community-id addresses-to-reveal airdrop-address]]
(fn [_ [community-id addresses-to-reveal airdrop-address share-future-addresses?]]
{:fx [[:dispatch [:communities/set-airdrop-address community-id airdrop-address]]
[:dispatch [:communities/set-share-all-addresses community-id share-future-addresses?]]
[:dispatch [:communities/set-addresses-to-reveal community-id addresses-to-reveal]]]}))
(rf/reg-event-fx :communities/edit-shared-addresses-failure
@@ -70,7 +70,7 @@
(is
(match?
{:db (-> (:db cofx)
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/selected-share-all-addresses community-id] true)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
:fx [[:dispatch
@@ -82,7 +82,7 @@
[:dispatch
[:communities/check-permissions-to-join-during-selection community-id
addresses-to-reveal]]]}
(sut/do-init-permission-addresses cofx [community-id revealed-accounts])))))
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true])))))
;; Expect to mark all addresses to be revealed and first one to receive
;; airdrops when no addresses were previously revealed.
@@ -93,7 +93,7 @@
(is
(match?
{:db (-> (:db cofx)
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/selected-share-all-addresses community-id] true)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
:fx [[:dispatch
[:communities/check-permissions-to-join-community
@@ -101,7 +101,7 @@
[:dispatch
[:communities/check-permissions-to-join-during-selection community-id
addresses-to-reveal]]]}
(sut/do-init-permission-addresses cofx [community-id revealed-accounts]))))))
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true]))))))
(deftest edit-shared-addresses-test
(testing
@@ -109,6 +109,7 @@
fallback to all wallet addresses"
(let [pub-key "abcdef"
revealed-addresses #{"0xB" "0xC"}
share-future-addresses? true
cofx {:db {:profile/profile {:public-key pub-key}
:communities/all-addresses-to-reveal {community-id revealed-addresses}}}
airdrop-address "0xB"
@@ -116,22 +117,24 @@
actual
(sut/edit-shared-addresses
cofx
[{:community-id community-id
:password password
:airdrop-address airdrop-address
:on-success (fn [new-addresses-to-reveal]
(is (match? revealed-addresses new-addresses-to-reveal)))}])
[{:community-id community-id
:password password
:airdrop-address airdrop-address
:share-future-addresses? share-future-addresses?
:on-success (fn [new-addresses-to-reveal]
(is (match? revealed-addresses new-addresses-to-reveal)))}])
on-success-wrapper (-> actual :fx first second :on-success)]
(is (match?
{:fx [[:effects.community/edit-shared-addresses
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal revealed-addresses
:airdrop-address airdrop-address
:on-success fn?
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal revealed-addresses
:share-future-addresses? share-future-addresses?
:airdrop-address airdrop-address
:on-success fn?
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
actual))
(on-success-wrapper)))
@@ -203,7 +203,9 @@
:addresses-for-permissions])
(rf/dispatch [:hide-bottom-sheet]))}]))}])
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses]))
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal])))
(do
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses])
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal]))))
highest-role (rf/sub [:communities/highest-role-for-selection id])
[unmodified-role _] (rn/use-state highest-role)]
@@ -261,6 +263,7 @@
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
wallet-accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])
joined (rf/sub [:communities/community-joined id])
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)
@@ -285,7 +288,6 @@
(set-flag-share-all-addresses new-value)
(when new-value
(set-addresses-to-reveal (set (map :address wallet-accounts))))))]
(rn/use-mount
(fn []
(when-not flag-share-all-addresses
@@ -310,6 +312,7 @@
flag-share-all-addresses]
:header [quo/page-setting
{:checked? flag-share-all-addresses
:disabled? joined
:customization-color color
:on-change toggle-flag-share-all-addresses
:setting-text (i18n/label
+14 -18
View File
@@ -16,6 +16,7 @@
[status-im.navigation.events :as navigation]
[status-im.navigation.transitions :as transitions]
[taoensso.timbre :as log]
[utils.collection :as collection-utils]
[utils.re-frame :as rf]))
(defn handle-community
@@ -372,15 +373,14 @@
(when (and community joined (not fetching-revealed-accounts))
{:db (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
:json-rpc/call
[{:method "wakuext_getRevealedAccounts"
:params [community-id (get-in db [:profile/profile :public-key])]
:js-response true
:on-success [:communities/get-revealed-accounts-success community-id on-success]
:on-error (fn [err]
(log/error {:message "failed to fetch revealed accounts"
:community-id community-id
:err err})
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
[{:method "wakuext_latestRequestToJoinForCommunity"
:params [community-id]
:on-success [:communities/get-revealed-accounts-success community-id on-success]
:on-error (fn [err]
(log/error {:message "failed to fetch revealed accounts"
:community-id community-id
:err err})
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
(rf/reg-event-fx :communities/get-revealed-accounts get-revealed-accounts)
@@ -399,22 +399,18 @@
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :communities/get-revealed-accounts-success
(fn [{:keys [db]} [community-id on-success revealed-accounts-js]]
(fn [{:keys [db]} [community-id on-success request-to-join]]
(when-let [community (get-in db [:communities community-id])]
(let [revealed-accounts
(reduce
(fn [acc {:keys [address] :as revealed-account}]
(assoc acc address revealed-account))
{}
(data-store.communities/<-revealed-accounts-rpc revealed-accounts-js))
(let [revealed-accounts (collection-utils/index-by :address (:revealedAccounts request-to-join))
share-future-addresses? (:shareFutureAddresses request-to-join)
community-with-revealed-accounts
(-> community
(assoc :revealed-accounts revealed-accounts)
(assoc :share-future-addresses? share-future-addresses?)
(dissoc :fetching-revealed-accounts))]
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)
:fx [(when (vector? on-success)
[:dispatch (conj on-success revealed-accounts)])]}))))
[:dispatch (conj on-success revealed-accounts share-future-addresses?)])]}))))
(rf/reg-event-fx :communities/get-revealed-accounts-failed
(fn [{:keys [db]} [community-id]]
@@ -146,8 +146,8 @@
effects (events/get-revealed-accounts {:db db} [community-id])]
(is (match? (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
(:db effects)))
(is (match? {:method "wakuext_getRevealedAccounts"
:params [community-id "profile-public-key"]}
(is (match? {:method "wakuext_latestRequestToJoinForCommunity"
:params [community-id]}
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
(deftest handle-community-test
@@ -117,13 +117,14 @@
{:community community-name})}]]]})))
(defn request-to-join-with-signatures
[_ [community-id addresses-to-reveal signatures]]
[_ [community-id addresses-to-reveal signatures share-future-addresses?]]
{:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress (first addresses-to-reveal)}]
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:shareFutureAddresses share-future-addresses?
:airdropAddress (first addresses-to-reveal)}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]]})
@@ -153,16 +154,18 @@
(defn request-to-join-with-addresses
[{:keys [db]}
[{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
share-future-addresses? (get-in db [:communities/selected-share-all-addresses community-id])
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
{:fx [[:effects.community/request-to-join
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address airdrop-address
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]}))
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address airdrop-address
:share-future-addresses? share-future-addresses?
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]}))
(rf/reg-event-fx :communities/request-to-join-with-addresses request-to-join-with-addresses)
@@ -37,19 +37,22 @@
(sut/sign-data cofx [community-id password sign-params])))))
(deftest request-to-join-with-signatures-test
(let [cofx {:db {}}
addresses-to-reveal [account-pub-key "0x2"]
signatures ["11111" "222222"]
expected {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress "0x1"}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error
community-id]}]]]}]
(let [cofx {:db {}}
addresses-to-reveal [account-pub-key "0x2"]
share-future-addresses? true
signatures ["11111" "222222"]
expected {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:shareFutureAddresses share-future-addresses?
:airdropAddress "0x1"}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error
community-id]}]]]}]
(is (match? expected
(sut/request-to-join-with-signatures cofx
[community-id addresses-to-reveal signatures])))))
[community-id addresses-to-reveal signatures
share-future-addresses?])))))
@@ -5,13 +5,8 @@
(def background-container
{:background-color colors/neutral-100
:flex-direction :row
:position :absolute
:overflow :hidden
:top 0
:bottom 0
:left 0
:right 0})
:flex 1
:overflow :hidden})
(def background-blur-overlay
{:position :absolute
@@ -25,13 +25,12 @@
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
(defn background-image
[content-width]
[image-view-width]
[rn/image
{:resize-mode :stretch
:resize-method :scale
:style {:top 138
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
{:resize-mode :stretch
:style {:flex 1
:width image-view-width}
:source (resources/get-image :onboarding-illustration)}])
(defonce progress (atom nil))
(defonce paused? (atom nil))
@@ -5,12 +5,9 @@
(defn header-container
[status-bar-height content-width index header-background]
{:position :absolute
:top 0
:left (* content-width index)
{:margin-left (* content-width index)
:padding-top (+ 30 status-bar-height)
:width content-width
:height (+ 96 status-bar-height)
:flex-direction :row
:background-color (when header-background colors/onboarding-header-black)})
@@ -62,9 +59,9 @@
:top (+ 12 status-bar-height)})
(defn carousel-container
[left animate?]
(cond->> {:position :absolute
:top 0
:flex-direction :row
:left left}
animate? (reanimated/apply-animations-to-style {:left left})))
[left animate? width]
(cond->> {:flex-direction :row
:flex 1
:width width
:margin-left left}
animate? (reanimated/apply-animations-to-style {:margin-left left})))
@@ -18,19 +18,18 @@
:size :heading-2}
(get-in header-text [index :text])]
[quo/text
{:style style/carousel-sub-text
:size :paragraph-1}
{:style style/carousel-sub-text}
(get-in header-text [index :sub-text])]])
(defn content-view
[{:keys [window-width status-bar-height index header-text header-background]} content]
(let [content-width (* 4 window-width)]
[:<>
(when content content)
[rn/view {:style {:flex 1}}
[rn/view {:style (style/header-container status-bar-height content-width index header-background)}
(for [index (range 4)]
^{:key index}
[header-text-view index window-width header-text])]]))
[header-text-view index window-width header-text])]
(when content content)]))
(defn progress-bar
[{:keys [static? progress-bar-width]}]
@@ -64,10 +63,10 @@
:swipeable (animation/composed-gestures progress paused? is-dragging? drag-amount)
:tappable (animation/tap-gesture progress paused?)
nil)]
[:<>
[rn/view {:style {:flex 1}}
[gesture/gesture-detector {:gesture identified-gesture}
[container-view {:style (style/carousel-container carousel-left animate?)}
(for [index (range 2)]
[container-view {:style (style/carousel-container carousel-left animate? (* 4 window-width))}
(for [index (range 1)]
^{:key index}
[content-view
{:window-width window-width
@@ -5,6 +5,7 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
@@ -126,6 +127,7 @@
(defn- internal-view
[sign-in-type]
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
@@ -4,20 +4,20 @@
(def title-container
{:margin-horizontal 20
:padding-vertical 12})
:padding-bottom 20
:padding-top 12})
(defn page-container
[insets]
{:flex 1
:justify-content :space-between
:padding-top (+ (:top insets) 56)})
{:flex 1
:padding-top (+ (:top insets) 56)})
(defn page-illustration
[width]
{:flex 1
:padding-top 12
:padding-bottom 10
:width width})
{:flex 1
:margin-top 12
:margin-bottom 10
:width width})
(defn buttons
[insets]
@@ -2,11 +2,16 @@
(defn page-container
[insets]
{:flex 1
:justify-content :space-between
:padding-top (:top insets)})
{:flex 1
:padding-top (:top insets)})
(defn page-illustration
[width]
{:flex 1
:width width})
(def title-style
{:position :absolute
:left 0
:right 0
:top 0})
@@ -17,19 +17,22 @@
(defn generate-keys-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20}
{:container-style {:margin-horizontal 20
:margin-vertical 12}
:title (i18n/label :t/generating-keys)}])
(defn saving-keys-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20}
{:container-style {:margin-horizontal 20
:margin-vertical 12}
:title (i18n/label :t/saving-keys-to-device)}])
(defn keys-saved-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20}
{:container-style {:margin-horizontal 20
:margin-vertical 12}
:title (i18n/label :t/keys-saved)}])
(defn sequence-animation
@@ -61,46 +64,42 @@
reanimated/easings))))))
(defn title
[insets]
(let [top-insets (+ (if rn/small-screen? 62 112) (:insets insets))
generate-keys-opacity (reanimated/use-shared-value 1)
[]
(let [generate-keys-opacity (reanimated/use-shared-value 1)
saving-keys-opacity (reanimated/use-shared-value 0)
keys-saved-opacity (reanimated/use-shared-value 0)]
(sequence-animation generate-keys-opacity saving-keys-opacity keys-saved-opacity)
[rn/view
{:position :absolute
:top top-insets}
{:style {:margin-top 56
:height 56}}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity generate-keys-opacity}
{:position :absolute})}
style/title-style)}
[generate-keys-title]]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity saving-keys-opacity}
{:position :absolute})}
style/title-style)}
[saving-keys-title]]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity keys-saved-opacity}
{:position :absolute})}
style/title-style)}
[keys-saved-title]]]))
(defn content
[]
(let [width (:width (rn/get-window))]
[rn/view
{:top 156
:position :absolute}
[rn/image
{:resize-mode :contain
:style (style/page-illustration width)
:source (resources/get-image :generate-keys1)}]]))
[rn/image
{:resize-mode :contain
:style (style/page-illustration width)
:source (resources/get-image :generate-keys1)}]))
(defn view
[]
(let [insets (safe-area/get-insets)]
[rn/view {:style (style/page-container insets)}
[:<>
[title insets]
[title]
[content]]]))
@@ -7,9 +7,8 @@
:justify-content :flex-end})
(def text-container
{:flex 1
:text-align :center
:margin-top 16
{:text-align :center
:margin-top 4
:flex-wrap :wrap})
(def plain-text
@@ -19,9 +18,8 @@
{:flex 1
:color colors/white})
(def bottom-actions-container
{:position :absolute
:background-color colors/onboarding-header-black
:left 0
:right 0
:padding-bottom 40})
(defn bottom-actions-container
[bottom-insets]
{:background-color colors/onboarding-header-black
:flex-shrink 1
:padding-bottom (+ 20 bottom-insets)})
@@ -2,6 +2,7 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.common.overlay.view :as overlay]
[status-im.contexts.onboarding.intro.style :as style]
@@ -14,7 +15,7 @@
[rn/view {:style style/page-container}
[background/view false]
[quo/bottom-actions
{:container-style style/bottom-actions-container
{:container-style (style/bottom-actions-container (safe-area/get-bottom))
:actions :two-vertical-actions
:description :bottom
:description-text [quo/text
@@ -170,6 +170,7 @@
[status-im.contexts.preview.quo.settings.settings-item :as settings-item]
[status-im.contexts.preview.quo.share.qr-code :as qr-code]
[status-im.contexts.preview.quo.share.share-qr-code :as share-qr-code]
[status-im.contexts.preview.quo.slideshow.slider-bar :as slider-bar]
[status-im.contexts.preview.quo.style :as style]
[status-im.contexts.preview.quo.switcher.group-messaging-card :as
group-messaging-card]
@@ -211,6 +212,7 @@
[status-im.contexts.preview.quo.wallet.progress-bar :as progress-bar]
[status-im.contexts.preview.quo.wallet.required-tokens :as required-tokens]
[status-im.contexts.preview.quo.wallet.summary-info :as summary-info]
[status-im.contexts.preview.quo.wallet.swap-input :as swap-input]
[status-im.contexts.preview.quo.wallet.token-input :as token-input]
[status-im.contexts.preview.quo.wallet.transaction-progress :as transaction-progress]
[status-im.contexts.preview.quo.wallet.transaction-summary :as
@@ -502,6 +504,8 @@
:component qr-code/view}
{:name :share-qr-code
:component share-qr-code/view}]
:slideshow [{:name :slider-bar
:component slider-bar/view}]
:switchers [{:name :group-messaging-card
:component group-messaging-card/view}
{:name :switcher-cards
@@ -567,6 +571,7 @@
{:name :required-tokens
:component required-tokens/view}
{:name :summary-info :component summary-info/view}
{:name :swap-input :component swap-input/view}
{:name :token-input :component token-input/view}
{:name :wallet-activity :component wallet-activity/view}
{:name :transaction-progress :component transaction-progress/view}
@@ -0,0 +1,49 @@
(ns status-im.contexts.preview.quo.slideshow.slider-bar
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:key :total-amount
:type :number}
{:label "Blur (dark only)?"
:key :blur?
:type :boolean}
(preview/customization-color-option)])
(defn view
[]
(let [[state set-state] (rn/use-state {:total-amount 10
:active-index 0
:blur? false
:customization-color :blue})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor
:blur? (:blur? state)
:show-blur-background? true
:blur-dark-only? true}
[rn/view
{:style {:flex-direction :row
:justify-content :center
:gap 10
:padding 10}}
[quo/button
{:type :outline
:style {:disabled true}
:disabled? (zero? (:active-index state))
:icon-only? true
:on-press (fn []
(set-state (update state :active-index dec)))}
:i/chevron-left]
[quo/button
{:type :outline
:disabled? (= (:active-index state)
(dec (:total-amount state)))
:icon-only? true
:on-press (fn []
(set-state (update state :active-index inc)))}
:i/chevron-right]]
[quo/slider-bar state]]))
@@ -0,0 +1,68 @@
(ns status-im.contexts.preview.quo.wallet.swap-input
(: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 :select
:key :type
:options [{:key :pay}
{:key :receive}]}
{:type :select
:key :status
:options [{:key :default}
{:key :disabled}
{:key :loading}]}
{:type :select
:key :value
:options [{:key :token}
{:key :fiat}]}
{:type :boolean
:key :error?}
{:type :boolean
:key :enable-swap?}
{:type :boolean
:key :show-approval-label?}
(preview/customization-color-option)])
(defn view
[]
(let [[state set-state] (rn/use-state {:type :pay
:error? false
:token "SNT"
:customization-color :blue
:show-approval-label? false
:enable-swap? true
:status :default
:currency-symbol "€"})
[value set-value] (rn/use-state "")
on-press (fn [v] (set-value (str value v)))
delete (fn [] (set-value #(subs % 0 (dec (count %)))))]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/swap-input
(assoc state
:on-swap-press #(js/alert "Swap Pressed")
:on-token-press #(js/alert "Token Pressed")
:on-max-press #(js/alert "Max Pressed")
:value value
:fiat-value (str (.toFixed (* value 0.3) 2))
:container-style {:margin-bottom 20}
:network-tag-props {:title "Max: 200 SNT"
:networks [{:source (resources/get-network :ethereum)}]}
:approval-label-props
{:status :approve
:token-value "10"
:button-props {:on-press
#(js/alert "Approve Pressed")}
:customization-color (:customization-color state)
:token-symbol "SNT"})]
[quo/numbered-keyboard
{:left-action :dot
:delete-key? true
:on-press on-press
:on-delete delete}]]))
+15 -13
View File
@@ -29,19 +29,21 @@
[]
(let [log-enabled? (boolean (not-empty config/log-level))]
(assoc (login)
:deviceName (native-module/get-installation-name)
:rootDataDir (native-module/backup-disabled-data-dir)
:rootKeystoreDir (native-module/keystore-dir)
:logLevel (when log-enabled? config/log-level)
:logEnabled log-enabled?
:logFilePath (native-module/log-file-directory)
:verifyTransactionURL config/verify-transaction-url
:verifyENSURL config/verify-ens-url
:verifyENSContractAddress config/verify-ens-contract-address
:verifyTransactionChainID config/verify-transaction-chain-id
:wakuV2LightClient true
:previewPrivacy config/blank-preview?
:testNetworksEnabled config/test-networks-enabled?)))
:deviceName (native-module/get-installation-name)
:rootDataDir (native-module/backup-disabled-data-dir)
:rootKeystoreDir (native-module/keystore-dir)
:logLevel (when log-enabled? config/log-level)
:logEnabled log-enabled?
:logFilePath (native-module/log-file-directory)
:verifyTransactionURL config/verify-transaction-url
:verifyENSURL config/verify-ens-url
:verifyENSContractAddress config/verify-ens-contract-address
:verifyTransactionChainID config/verify-transaction-chain-id
:wakuV2LightClient true
:wakuV2Fleet config/fleet
:wakuV2EnableStoreConfirmationForMessagesSent false
:previewPrivacy config/blank-preview?
:testNetworksEnabled config/test-networks-enabled?)))
(defn strip-file-prefix
[path]
@@ -7,6 +7,7 @@
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.confirmation-drawer.view :as confirmation-drawer]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.config :as config]
[status-im.constants :as constants]
@@ -254,6 +255,7 @@
(defn view
[]
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
(let [[show-profiles? set-show-profiles] (rn/use-state false)
show-profiles (rn/use-callback #(set-show-profiles true))
hide-profiles (rn/use-callback #(set-show-profiles false))]
@@ -113,7 +113,8 @@
(defn view
[]
(let [profile-color (rf/sub [:profile/customization-color])
(let [view-id (rf/sub [:view-id])
profile-color (rf/sub [:profile/customization-color])
accounts-addresses (rf/sub [:wallet/addresses])
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
[address-or-ens set-address-or-ens] (rn/use-state "")
@@ -175,11 +176,12 @@
:on-press navigate-back
:margin-top (safe-area/get-top)
:accessibility-label :add-address-to-save-page-nav}]
:footer [quo/button
{:customization-color profile-color
:disabled? button-disabled?
:on-press on-press-continue}
(i18n/label :t/continue)]}
:footer (when (= view-id :screen/settings.add-address-to-save)
[quo/button
{:customization-color profile-color
:disabled? button-disabled?
:on-press on-press-continue}
(i18n/label :t/continue)])}
[quo/page-top
{:container-style style/header-container
:blur? true
@@ -121,7 +121,8 @@
:on-press on-press-save}
(i18n/label :t/save-address)]
:customization-color address-color
:gradient-cover? true}
:gradient-cover? true
:shell-overlay? true}
[quo/wallet-user-avatar
{:full-name (if (string/blank? address-label)
placeholder
@@ -0,0 +1,18 @@
(ns status-im.contexts.shell.activity-center.context
(:require
["react" :as react]
[oops.core :as oops]
[react-native.core :as rn]))
(defonce ^:private context
(react/createContext {}))
(defn provider
[state & children]
(into [:> (oops/oget context :Provider) {:value state}]
children))
(defn use-context
[]
(let [ctx (rn/use-context context)]
{:active-swipeable (oops/oget ctx :activeSwipeable)}))
@@ -15,10 +15,7 @@
(def defaults
{:filter-status :unread
:filter-type types/no-type
;; Choose the maximum number of notifications that *usually/safely* fit on
;; most screens, so that the UI doesn't have to needlessly render
;; notifications.
:notifications-per-page 8})
:notifications-per-page constants/notifications-per-page})
;;;; Navigation
@@ -1,6 +1,7 @@
(ns status-im.contexts.shell.activity-center.notification.admin.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -23,42 +24,50 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [active-swipeable notification extra-fn]} child]
(let [{:keys [community-id id membership-status]} notification]
[{:keys [notification extra-fn]} child]
(let [{:keys [community-id id
membership-status]} notification
accept (rn/use-callback
(fn []
(rf/dispatch [:communities/accept-request-to-join-pressed
community-id id]))
[community-id id])
decline (rn/use-callback
(fn []
(rf/dispatch [:communities/decline-request-to-join-pressed
community-id id]))
[community-id id])]
(cond
(#{constants/activity-center-membership-status-accepted
constants/activity-center-membership-status-declined}
membership-status)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child]
(= membership-status constants/activity-center-membership-status-pending)
[common/swipeable
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:communities/accept-request-to-join-pressed community-id id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:communities/decline-request-to-join-pressed community-id
id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press decline
:extra-fn extra-fn}
child]
:else
child)))
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
[{:keys [notification] :as props}]
(let [{:keys [author community-id id membership-status
read timestamp]} notification
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])]
[swipeable props
[quo/activity-log
{:title (i18n/label :t/join-request)
@@ -66,14 +75,13 @@
:icon :i/add-user
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:on-layout set-swipeable-height
:context [[common/user-avatar-tag author]
(i18n/label :t/wants-to-join)
[quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-logo community-logo
:community-name community-name}]]
:items (condp = membership-status
constants/activity-center-membership-status-accepted
@@ -4,6 +4,7 @@
(def swipe-action-width 80)
(def swipe-button-border-radius 16)
(def swipe-button-margin 8)
(def user-avatar-tag
{:background-color colors/white-opa-10})
@@ -1,10 +1,12 @@
(ns status-im.contexts.shell.activity-center.notification.common.view
(:require
[oops.core :as oops]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.activity-center.context :as ac.context]
[status-im.contexts.shell.activity-center.notification.common.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -14,7 +16,7 @@
(let [profile (rf/sub [:contacts/contact-by-identity user-id])]
[rn/view
{:on-start-should-set-responder
(fn [_event]
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile user-id])
true)}
@@ -33,35 +35,27 @@
swipe-button
swipeable-ref
style]}]
(fn [_ ^js drag-x]
(let [{:keys [height] :as extra} (extra-fn)
opacity (.interpolate drag-x interpolation-opacity)
translate-x (.interpolate drag-x interpolation-translate-x)]
(fn [_ drag-x]
(let [extra (extra-fn)
opacity (oops/ocall drag-x :interpolate interpolation-opacity)
translate-x (oops/ocall drag-x :interpolate interpolation-translate-x)]
[gesture/rect-button
{:style (merge {:border-radius style/swipe-button-border-radius} style)
:accessibility-label :notification-swipe-action-button
:on-press (fn []
(when @swipeable-ref
(.close ^js @swipeable-ref)
(oops/ocall @swipeable-ref :close)
(reset! active-swipeable nil))
(on-press extra))}
[swipe-button
{:style {:opacity opacity
:transform [{:translateX translate-x}]
:height height
:flex 1
:width style/swipe-action-width}}
extra]])))
(defn- close-active-swipeable
[active-swipeable swipeable]
(fn [_]
(when (and @active-swipeable
(not= @active-swipeable @swipeable))
(.close ^js @active-swipeable))
(reset! active-swipeable @swipeable)))
(defn swipe-button-container
[{:keys [style icon text]} _]
[{:keys [style icon text]}]
[rn/animated-view
{:accessibility-label :notification-swipe
:style style}
@@ -103,47 +97,54 @@
(rf/dispatch [:activity-center.notifications/delete (:id notification)]))
(defn swipeable
[_]
(let [swipeable-ref (atom nil)]
(fn [{:keys [active-swipeable
extra-fn
left-button
left-on-press
right-button
right-on-press]}
& children]
(into
[gesture/swipeable
(merge
{:ref #(reset! swipeable-ref %)
:accessibility-label :notification-swipeable
:friction 2
:on-swipeable-will-open (close-active-swipeable active-swipeable swipeable-ref)
:children-container-style {:padding-horizontal 20}}
(when left-button
{:overshoot-left false
:left-threshold style/swipe-action-width
:render-left-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/left-swipe-opacity-interpolation-js
:interpolation-translate-x
style/left-swipe-translate-x-interpolation-js
:on-press left-on-press
:swipe-button left-button
:swipeable-ref swipeable-ref
:style {:left 8}})})
(when right-button
{:overshoot-right false
:right-threshold style/swipe-action-width
:render-right-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/right-swipe-opacity-interpolation-js
:interpolation-translate-x
style/right-swipe-translate-x-interpolation-js
:on-press right-on-press
:swipe-button right-button
:swipeable-ref swipeable-ref
:style {:right -8}})}))]
children))))
[{:keys [extra-fn
left-button
left-on-press
right-button
right-on-press]}
child]
(let [{:keys [active-swipeable]} (ac.context/use-context)
this-swipeable (rn/use-ref-atom nil)
set-this-swipeable (rn/use-callback #(reset! this-swipeable %)
[this-swipeable])
on-swipeable-will-open (rn/use-callback
(fn []
(when (and @active-swipeable
(not= @active-swipeable @this-swipeable))
(oops/ocall @active-swipeable :close))
(reset! active-swipeable @this-swipeable))
[@active-swipeable @this-swipeable])]
[gesture/swipeable
(cond-> {:ref set-this-swipeable
:accessibility-label :notification-swipeable
:friction 2
:on-swipeable-will-open on-swipeable-will-open
:children-container-style {:padding-horizontal 20}}
left-button
(assoc :overshoot-left false
:left-threshold style/swipe-action-width
:render-left-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/left-swipe-opacity-interpolation-js
:interpolation-translate-x
style/left-swipe-translate-x-interpolation-js
:on-press left-on-press
:swipe-button left-button
:swipeable-ref this-swipeable
:style {:left style/swipe-button-margin}}))
right-button
(assoc :overshoot-right false
:right-threshold style/swipe-action-width
:render-right-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/right-swipe-opacity-interpolation-js
:interpolation-translate-x
style/right-swipe-translate-x-interpolation-js
:on-press right-on-press
:swipe-button right-button
:swipeable-ref this-swipeable
:style {:right (- style/swipe-button-margin)}})))
child]))
@@ -1,6 +1,7 @@
(ns status-im.contexts.shell.activity-center.notification.community-kicked.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -9,33 +10,34 @@
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [active-swipeable extra-fn]} child]
[{:keys [extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [community-id read
[{:keys [notification extra-fn]}]
(let [{:keys [id community-id read
timestamp]} notification
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:activity-center.notifications/mark-as-read (:id notification)]))}
community-image (get-in community [:images :thumbnail :uri])
customization-color (rf/sub [:profile/customization-color])
on-press (rn/use-callback
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
[id])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback {:on-press on-press}
[quo/activity-log
{:title (i18n/label :t/community-kicked-heading)
:customization-color customization-color
:icon :i/placeholder
:on-layout set-swipeable-height
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[quo/text {:style common-style/user-avatar-tag-text}
@@ -1,6 +1,7 @@
(ns status-im.contexts.shell.activity-center.notification.community-request.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
@@ -10,27 +11,23 @@
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [active-swipeable extra-fn]} child]
[{:keys [extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child])
(defn- get-header-text-and-context
[community membership-status]
(let [community-name (:name community)
permissions (:permissions community)
open? (not= 3 (:access permissions))
community-image (get-in community [:images :thumbnail :uri])
[community-logo community-name community-permissions membership-status]
(let [open? (not= 3 (:access community-permissions))
community-context-tag [quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-logo community-logo
:community-name community-name}]]
(cond
(= membership-status constants/activity-center-membership-status-idle)
@@ -56,27 +53,33 @@
:t/joined-community
:t/community-request-accepted-body-text)
(when open? {:community community-name}))]
community-context-tag]}
:else nil)))
community-context-tag]})))
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
[{:keys [notification extra-fn]}]
(let [{:keys [community-id membership-status read
timestamp]} notification
community (rf/sub [:communities/community community-id])
{:keys [header-text context]} (get-header-text-and-context community
membership-status)]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:communities/navigate-to-community-overview community-id]))}
timestamp]} notification
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
community-permissions (rf/sub [:communities/permissions community-id])
customization-color (rf/sub [:profile/customization-color])
{:keys [header-text
context]} (get-header-text-and-context community-logo
community-name
community-permissions
membership-status)
on-press (rn/use-callback
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:communities/navigate-to-community-overview
community-id]))
[community-id])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback {:on-press on-press}
[quo/activity-log
{:title header-text
:customization-color customization-color
:icon :i/communities
:on-layout set-swipeable-height
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context context}]]]))
@@ -1,6 +1,7 @@
(ns status-im.contexts.shell.activity-center.notification.contact-requests.view
(:require
[quo.core :as quo]
quo.theme
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
@@ -24,48 +25,52 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [active-swipeable extra-fn notification]} child]
[{:keys [extra-fn notification]} child]
(let [{:keys [id author message]} notification
{:keys [contact-request-state]} message
{:keys [public-key]} (rf/sub [:multiaccount/contact])
outgoing? (= public-key author)]
outgoing? (= public-key author)
accept (rn/use-callback
#(rf/dispatch [:activity-center.contact-requests/accept id])
[id])
decline (rn/use-callback
#(rf/dispatch [:activity-center.contact-requests/decline id])
[id])]
(cond
(or (#{constants/contact-request-message-state-accepted
constants/contact-request-message-state-declined}
contact-request-state)
(and outgoing? (= contact-request-state constants/contact-request-message-state-pending)))
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child]
(and (= contact-request-state constants/contact-request-message-state-pending)
(not outgoing?))
[common/swipeable
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.contact-requests/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.contact-requests/decline id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press decline
:extra-fn extra-fn}
child]
:else
child)))
(defn- outgoing-contact-request-view
[{:keys [notification set-swipeable-height customization-color]} theme]
[{:keys [notification]} theme]
(let [{:keys [chat-id message last-message accepted]} notification
{:keys [contact-request-state] :as message} (or message last-message)]
{:keys [contact-request-state] :as message} (or message last-message)
customization-color (rf/sub [:profile/customization-color])]
(if accepted
[quo/activity-log
{:title (i18n/label :t/contact-request-was-accepted)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -76,7 +81,6 @@
[quo/activity-log
{:title (i18n/label :t/contact-request)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -102,13 +106,22 @@
nil)}])))
(defn- incoming-contact-request-view
[{:keys [notification set-swipeable-height customization-color]} theme]
(let [{:keys [id author message last-message]} notification
message (or message last-message)]
[{:keys [notification]} theme]
(let [{:keys [id author message
last-message]} notification
customization-color (rf/sub [:profile/customization-color])
message (or message last-message)
accept (rn/use-callback
(fn []
(rf/dispatch [:activity-center.contact-requests/accept id]))
[id])
decline (rn/use-callback
(fn []
(rf/dispatch [:activity-center.contact-requests/decline id]))
[id])]
[quo/activity-log
{:title (i18n/label :t/contact-request)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -140,13 +153,13 @@
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-request
:on-press #(rf/dispatch [:activity-center.contact-requests/decline id])}
:on-press decline}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :accept-contact-request
:on-press #(rf/dispatch [:activity-center.contact-requests/accept id])}]
:on-press accept}]
nil)}]))
@@ -155,16 +168,16 @@
(let [{:keys [author message last-message]} notification
{:keys [public-key]} (rf/sub [:multiaccount/contact])
{:keys [contact-request-state]} (or message last-message)
app-theme (rf/sub [:theme])]
theme (quo.theme/use-theme)]
[swipeable props
(cond
(= public-key author)
[outgoing-contact-request-view props app-theme]
[outgoing-contact-request-view props theme]
(= contact-request-state constants/contact-request-message-state-accepted)
[rn/pressable
{:on-press #(rf/dispatch [:chat.ui/start-chat author])}
[incoming-contact-request-view props app-theme]]
[incoming-contact-request-view props theme]]
:else
[incoming-contact-request-view props app-theme])]))
[incoming-contact-request-view props theme])]))
@@ -105,7 +105,7 @@
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
(defn- swipeable
[{:keys [active-swipeable extra-fn notification replying?] :as props} child]
[{:keys [extra-fn notification replying?] :as props} child]
(let [{:keys [id message
contact-verification-status]} notification
challenger? (:outgoing message)]
@@ -116,23 +116,21 @@
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
[common/swipeable
{:left-button swipe-button-reply
:left-on-press #(prepare-challenge-reply props)
:right-button swipe-button-decline
:right-on-press #(decline-challenge id)
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button swipe-button-reply
:left-on-press #(prepare-challenge-reply props)
:right-button swipe-button-decline
:right-on-press #(decline-challenge id)
:extra-fn extra-fn}
child]
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
[common/swipeable
{:left-button swipe-button-trust
:left-on-press #(mark-challenge-trusted id)
:right-button swipe-button-untrustworthy
:right-on-press #(mark-challenge-untrustworthy id)
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button swipe-button-trust
:left-on-press #(mark-challenge-trusted id)
:right-button swipe-button-untrustworthy
:right-on-press #(mark-challenge-untrustworthy id)
:extra-fn extra-fn}
child]
(#{constants/contact-verification-status-accepted
@@ -140,12 +138,11 @@
constants/contact-verification-status-trusted}
contact-verification-status)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child]
:else
@@ -154,8 +151,9 @@
(defn view
[_]
(let [reply (atom "")]
(fn [{:keys [notification set-swipeable-height replying? customization-color] :as props}]
(let [{:keys [id message
(fn [{:keys [notification replying?] :as props}]
(let [customization-color (rf/sub [:profile/customization-color])
{:keys [id message
contact-verification-status]} notification
challenger? (:outgoing message)]
;; TODO(@ilmotta): Declined challenges should only be displayed for the challengee, not the
@@ -165,86 +163,84 @@
(= contact-verification-status constants/contact-verification-status-declined))
[swipeable props
[quo/activity-log
(merge
(when-not replying?
{:on-layout set-swipeable-height})
{:title (i18n/label :t/identity-verification-request)
:customization-color customization-color
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:on-update-reply #(reset! reply %)
:replying? replying?
:max-reply-length max-reply-length
:valid-reply? valid-reply?
:context (context-tags challenger? notification)
:message (activity-message challenger? notification)
:items
(cond-> []
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
(concat
[{:type :button
:subtype :danger
:key :button-mark-as-untrustworthy
:label (i18n/label :t/untrustworthy)
:accessibility-label :mark-contact-verification-as-untrustworthy
:on-press #(mark-challenge-untrustworthy id)}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :mark-contact-verification-as-trusted
:on-press #(mark-challenge-trusted id)}])
{:title (i18n/label :t/identity-verification-request)
:customization-color customization-color
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:on-update-reply #(reset! reply %)
:replying? replying?
:max-reply-length max-reply-length
:valid-reply? valid-reply?
:context (context-tags challenger? notification)
:message (activity-message challenger? notification)
:items
(cond-> []
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
(concat
[{:type :button
:subtype :danger
:key :button-mark-as-untrustworthy
:label (i18n/label :t/untrustworthy)
:accessibility-label :mark-contact-verification-as-untrustworthy
:on-press #(mark-challenge-untrustworthy id)}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :mark-contact-verification-as-trusted
:on-press #(mark-challenge-trusted id)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-trusted))
(concat [{:type :status
:subtype :positive
:key :status-trusted
:label (i18n/label :t/status-confirmed)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-trusted))
(concat [{:type :status
:subtype :positive
:key :status-trusted
:label (i18n/label :t/status-confirmed)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-untrustworthy))
(concat [{:type :status
:subtype :negative
:key :status-untrustworthy
:label (i18n/label :t/untrustworthy)}])
(and challenger?
(= contact-verification-status
constants/contact-verification-status-untrustworthy))
(concat [{:type :status
:subtype :negative
:key :status-untrustworthy
:label (i18n/label :t/untrustworthy)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-accepted))
(concat [{:type :status
:subtype :positive
:key :status-accepted
:label (i18n/label :t/replied)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-accepted))
(concat [{:type :status
:subtype :positive
:key :status-accepted
:label (i18n/label :t/replied)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-declined))
(concat [{:type :status
:subtype :negative
:key :status-declined
:label (i18n/label :t/declined)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-declined))
(concat [{:type :status
:subtype :negative
:key :status-declined
:label (i18n/label :t/declined)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
(concat
[{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-verification
:on-press #(decline-challenge id)}
(if replying?
{:type :button
:subtype :primary
:key :button-reply
:label (i18n/label :t/send-reply)
:accessibility-label :reply-to-contact-verification
:disable-when invalid-reply?
:on-press #(send-challenge-reply id @reply)}
{:type :button
:subtype :primary
:key :button-send-reply
:label (i18n/label :t/message-reply)
:accessibility-label :send-reply-to-contact-verification
:on-press #(prepare-challenge-reply props)})]))})]])))))
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
(concat
[{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-verification
:on-press #(decline-challenge id)}
(if replying?
{:type :button
:subtype :primary
:key :button-reply
:label (i18n/label :t/send-reply)
:accessibility-label :reply-to-contact-verification
:disable-when invalid-reply?
:on-press #(send-challenge-reply id @reply)}
{:type :button
:subtype :primary
:key :button-send-reply
:label (i18n/label :t/message-reply)
:accessibility-label :send-reply-to-contact-verification
:on-press #(prepare-challenge-reply props)})]))}]])))))
@@ -1,6 +1,7 @@
(ns status-im.contexts.shell.activity-center.notification.membership.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -33,35 +34,50 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [active-swipeable notification extra-fn]} child]
(let [{:keys [accepted dismissed id]} notification]
[{:keys [notification extra-fn]} child]
(let [{:keys [accepted dismissed
id]} notification
accept (rn/use-callback
(fn [] (rf/dispatch [:activity-center.notifications/accept id]))
[id])
dismiss (rn/use-callback
(fn [] (rf/dispatch [:activity-center.notifications/dismiss id]))
[id])]
(if (or accepted dismissed)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child]
[common/swipeable
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.notifications/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.notifications/dismiss id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press dismiss
:extra-fn extra-fn}
child])))
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [id accepted dismissed author read timestamp chat-name chat-id]} notification]
[{:keys [notification] :as props}]
(let [{:keys [id accepted dismissed author read
timestamp chat-name
chat-id]} notification
customization-color (rf/sub [:profile/customization-color])
accept (rn/use-callback
(fn []
(rf/dispatch [:activity-center.notifications/accept id]))
[id])
dismiss (rn/use-callback
(fn []
(rf/dispatch [:activity-center.notifications/dismiss id]))
[id])]
[swipeable props
[pressable {:accepted accepted :chat-id chat-id}
[quo/activity-log
{:title (i18n/label :t/added-to-group-chat)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -78,13 +94,10 @@
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :accept-group-chat-invitation
:on-press #(rf/dispatch
[:activity-center.notifications/accept id])}
:on-press accept}
{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-group-chat-invitation
:on-press #(rf/dispatch
[:activity-center.notifications/dismiss
id])}])}]]]))
:on-press dismiss}])}]]]))
@@ -30,25 +30,24 @@
parsed-text-children))))
(defn- swipeable
[{:keys [active-swipeable extra-fn]} child]
[{:keys [extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
[{:keys [notification extra-fn]}]
(let [{:keys [author chat-name community-id chat-id
message read timestamp]} notification
community-chat? (not (string/blank? community-id))
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
@@ -56,7 +55,6 @@
[quo/activity-log
{:title (i18n/label :t/mention)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/mention
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -68,7 +66,7 @@
{:type :channel
:blur? true
:size 24
:community-logo community-image
:community-logo community-logo
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
@@ -51,26 +51,26 @@
nil))
(defn- swipeable
[{:keys [active-swipeable extra-fn]} child]
[{:keys [extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification set-swipeable-height customization-color] :as props}]
[{:keys [notification extra-fn]}]
(let [{:keys [author chat-name community-id chat-id
message read timestamp album-messages]} notification
community-chat? (not (string/blank? community-id))
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])
media-server-port (rf/sub [:mediaserver/port])]
[swipeable props
message read timestamp
album-messages]} notification
community-chat? (not (string/blank? community-id))
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])
media-server-port (rf/sub [:mediaserver/port])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
@@ -78,7 +78,6 @@
[quo/activity-log
{:title (i18n/label :t/message-reply)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/reply
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -89,7 +88,7 @@
{:type :channel
:blur? true
:size 24
:community-logo community-image
:community-logo community-logo
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
@@ -113,10 +112,7 @@
(= (:content-type message)
constants/content-type-gif)
:gif
:else
nil)
:gif)
:body (get-message-content message
album-messages
media-server-port)}}]]]))
@@ -1,9 +1,10 @@
(ns status-im.contexts.shell.activity-center.view
(:require
[oops.core :as oops]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.navigation :as navigation]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.context :as ac.context]
[status-im.contexts.shell.activity-center.header.view :as header]
[status-im.contexts.shell.activity-center.notification-types :as types]
[status-im.contexts.shell.activity-center.notification.admin.view :as admin]
@@ -23,61 +24,68 @@
[utils.re-frame :as rf]))
(defn notification-component
[{:keys [type] :as notification} index]
(let [extra-fn (rn/use-callback
(fn []
{:notification notification})
[notification])
props {:notification notification
:extra-fn extra-fn}]
;; Notifications are expensive to render. Without `delay-render` the opening
;; animation of the Activity Center can be clunky and the time to open the
;; AC after pressing the bell icon can be high.
[rn/view {:style (style/notification-container index)}
(cond
(= type types/contact-verification)
[contact-verification/view props]
(= type types/contact-request)
[contact-requests/view props]
(= type types/mention)
[mentions/view props]
(= type types/reply)
[reply/view props]
(= type types/admin)
[admin/view props]
(some types/membership [type])
(condp = type
types/private-group-chat [membership/view props]
types/community-request [community-request/view props]
types/community-kicked [community-kicked/view props]
nil))]))
(defn- fetch-next-page
[]
(let [height (atom 0)
set-swipeable-height #(reset! height (oops/oget % "nativeEvent.layout.height"))]
(fn [{:keys [type] :as notification} index _ {:keys [active-swipeable customization-color]}]
(let [props {:height height
:customization-color customization-color
:active-swipeable active-swipeable
:set-swipeable-height set-swipeable-height
:notification notification
:extra-fn (fn [] {:height @height :notification notification})}]
[rn/view {:style (style/notification-container index)}
(cond
(= type types/contact-verification)
[contact-verification/view props]
(= type types/contact-request)
[contact-requests/view props]
(= type types/mention)
[mentions/view props]
(= type types/reply)
[reply/view props]
(= type types/admin)
[admin/view props]
(some types/membership [type])
(condp = type
types/private-group-chat [membership/view props]
types/community-request [community-request/view props]
types/community-kicked [community-kicked/view props]
nil)
:else
nil)]))))
(rf/dispatch [:activity-center.notifications/fetch-next-page]))
(defn view
[]
(let [active-swipeable (atom nil)]
(rf/dispatch [:activity-center.notifications/fetch-first-page])
(fn []
(let [notifications (rf/sub [:activity-center/notifications])
customization-color (rf/sub [:profile/customization-color])]
[quo/overlay {:type :shell}
[rn/view {:flex 1 :padding-top (navigation/status-bar-height)}
[header/header]
[rn/flat-list
{:data notifications
:render-data {:active-swipeable active-swipeable
:customization-color customization-color}
:content-container-style {:flex-grow 1}
:empty-component [empty-tab/empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
:render-fn notification-component}]]
]))))
(let [notifications (rf/sub [:activity-center/notifications])
;; We globally control the active swipeable for all notifications
;; because when a swipe left/right gesture initiates, the previously
;; active swiped notification (if any) must be removed & closed with
;; animation.
active-swipeable (rn/use-ref-atom nil)]
(rn/use-mount
(fn []
(rf/dispatch [:activity-center.notifications/fetch-first-page])))
[ac.context/provider {:active-swipeable active-swipeable}
[quo/overlay {:type :shell}
[rn/view {:style {:flex 1 :padding-top (navigation/status-bar-height)}}
[header/header]
(rn/delay-render
[rn/flat-list
{:data notifications
:initial-num-to-render constants/notifications-per-page
:content-container-style {:flex-grow 1}
:empty-component [empty-tab/empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached fetch-next-page
:render-fn notification-component}])]]]))
@@ -117,13 +117,14 @@
(defn- f-internal-view
[]
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)]
[:<>
(when keyboard-shown
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:share-button? true
:on-success-scan on-qr-code-scanned}]]))
(rn/use-mount
(fn []
(when keyboard-shown
(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
[]
@@ -1,18 +0,0 @@
(ns status-im.contexts.shell.share.wallet.style
(:require
[quo.foundations.colors :as colors]))
(defn indicator-wrapper-style
[active?]
{:width 8
:height 8
:border-radius 4
:background-color colors/white
:opacity (if active? 1.0 0.5)})
(def indicator-list-style
{:display :flex
:flex-direction :row
:align-items :center
:justify-content :center
:gap 8})
@@ -6,7 +6,6 @@
[react-native.platform :as platform]
[reagent.core :as reagent]
[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]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.sheets.network-preferences.view :as network-preferences]
@@ -85,16 +84,6 @@
:on-legacy-press on-legacy-press
:on-settings-press on-settings-press}]]]))))
(defn- indicator
[active?]
[rn/view {:style (wallet-style/indicator-wrapper-style active?)}])
(defn- indicator-list
[num-indicators current-index]
[rn/view {:style wallet-style/indicator-list-style}
(for [i (range num-indicators)]
^{:key i} [indicator (= current-index i)])])
(defn render-item
[{:keys [address] :as account}]
[wallet-qr-code-item
@@ -136,4 +125,7 @@
:render-fn render-item}]
(when (> num-accounts 1)
[rn/view {:style {:margin-top 20}}
[indicator-list num-accounts @current-index]])]))))
[quo/slider-bar
{:total-amount num-accounts
:active-index @current-index
:blur? true}]])]))))
@@ -185,7 +185,7 @@
;; We delay the navigation because we need re-frame to update the DB on time.
;; By doing it, we skip a blink while visiting the collectible detail page.
[:dispatch-later
{:ms 1
{:ms 17
:dispatch [:navigate-to :screen/wallet.collectible]}]]})))
(defn- keep-not-empty-value
@@ -79,12 +79,20 @@
(rf/dispatch [:wallet/clear-collectible-details]))
(defn animated-header
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme id]}]
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
layer-opacity (header-animations/use-layer-opacity
scroll-amount
(colors/theme-colors colors/white-opa-0 colors/neutral-95-opa-0 theme)
(colors/theme-colors colors/white-opa-50 colors/neutral-95-opa-70-blur theme))]
[{:keys [scroll-amount title-opacity page-nav-type theme]}]
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
layer-opacity (header-animations/use-layer-opacity
scroll-amount
(colors/theme-colors colors/white-opa-0
colors/neutral-95-opa-0
theme)
(colors/theme-colors colors/white-opa-50
colors/neutral-95-opa-70-blur
theme))
{{preview-uri :uri} :preview-url
{title :name} :collectible-data
{description :name} :collection-data
id :id} (rf/sub [:wallet/collectible-details])]
[rn/view {:style (style/animated-header)}
[reanimated/blur-view
{:style {:flex 1
@@ -97,7 +105,7 @@
[reanimated/view {:style layer-opacity}
[quo/page-nav
{:type page-nav-type
:picture picture
:picture preview-uri
:title title
:description description
:background :blur
@@ -110,7 +118,7 @@
{:content (fn []
[options-drawer/view
{:name title
:image picture
:image preview-uri
:id id}])
:theme theme}])}]
:center-opacity title-opacity}]]]]))
@@ -144,10 +152,11 @@
[_]
(let [selected-tab (reagent/atom :overview)
on-tab-change #(reset! selected-tab %)]
(fn [{:keys [collectible set-title-bottom theme]}]
(fn [{:keys [set-title-bottom theme]}]
(let [title-ref (rn/use-ref-atom nil)
set-title-ref (rn/use-callback #(reset! title-ref %))
animation-shared-element-id (rf/sub [:animation-shared-element-id])
collectible (rf/sub [:wallet/collectible-details])
collectible-owner (rf/sub [:wallet/collectible-details-owner collectible])
aspect-ratio (rf/sub [:wallet/collectible-aspect-ratio])
gradient-color (rf/sub [:wallet/collectible-gradient-color])
@@ -196,14 +205,14 @@
token-id
{:images [collectible-image]
:index 0
:on-options-press #(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[options-drawer/view
{:name collectible-name
:image
preview-uri
:id id}])}])}])))
:on-options-press #(rf/dispatch
[:show-bottom-sheet
{:content
(fn []
[options-drawer/view
{:name collectible-name
:image preview-uri
:id id}])}])}])))
:on-collectible-load (fn []
;; We need to delay the measurement because the
;; navigation has an animation
@@ -241,33 +250,24 @@
(defn view
[_]
(let [{:keys [top]} (safe-area/get-insets)
theme (quo.theme/use-theme)
title-bottom-coord (rn/use-ref-atom 0)
set-title-bottom (rn/use-callback
(fn [_ y _ height]
(reset! title-bottom-coord
(get-title-bottom-y-position y height))))
scroll-amount (reanimated/use-shared-value 0)
title-opacity (reanimated/use-shared-value 0)
{:keys [collection-data
collectible-data
preview-url]
:as collectible} (rf/sub [:wallet/collectible-details])]
(let [{:keys [top]} (safe-area/get-insets)
theme (quo.theme/use-theme)
title-bottom-coord (rn/use-ref-atom 0)
set-title-bottom (rn/use-callback
(fn [_ y _ height]
(reset! title-bottom-coord
(get-title-bottom-y-position y height))))
scroll-amount (reanimated/use-shared-value 0)
title-opacity (reanimated/use-shared-value 0)]
[rn/view {:style (style/background-color theme)}
[animated-header
{:id (:id collectible)
:scroll-amount scroll-amount
{:scroll-amount scroll-amount
:title-opacity title-opacity
:page-nav-type :title-description
:picture (:uri preview-url)
:title (:name collectible-data)
:description (:name collection-data)
:theme theme}]
[reanimated/scroll-view
{:style (style/scroll-view top)
:on-scroll #(on-scroll % scroll-amount title-opacity title-bottom-coord)}
[collectible-details
{:collectible collectible
:set-title-bottom set-title-bottom
{:set-title-bottom set-title-bottom
:theme theme}]]]))
@@ -4,12 +4,19 @@
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(defonce ^:private request-id-atom (atom 0))
(defn- get-unique-request-id
[]
(swap! request-id-atom inc)
@request-id-atom)
(rf/reg-event-fx
:wallet/fetch-activities-for-current-account
(fn [{:keys [db]}]
(let [address (-> db :wallet :current-viewing-account-address)
chain-ids (chain/chain-ids db)
request-id 0
request-id (get-unique-request-id)
filters {:period {:startTimestamp 0
:endTimestamp 0}
:types []
@@ -20,9 +27,10 @@
:filterOutAssets false
:filterOutCollectibles false}
offset 0
limit 35
limit 50
request-params [request-id [address] chain-ids filters offset limit]]
{:fx [[:json-rpc/call
{:db (assoc-in db [:wallet :ui :activity-tab :request request-id] address)
:fx [[:json-rpc/call
[{;; This method is deprecated and will be replaced by
;; "wallet_startActivityFilterSession"
;; https://github.com/status-im/status-mobile/issues/19864
@@ -32,13 +40,31 @@
{:event :wallet/fetch-activities-for-current-account
:params request-params}]}]]]})))
(def ^:private activity-transaction-id (comp hash :transaction))
(rf/reg-event-fx
:wallet/activity-filtering-for-current-account-done
(fn [{:keys [db]} [{:keys [message]}]]
(let [address (-> db :wallet :current-viewing-account-address)
activities (->> message
(transforms/json->clj)
(:activities)
(cske/transform-keys transforms/->kebab-case-keyword))
sorted-activities (sort :timestamp activities)]
{:db (assoc-in db [:wallet :activities address] sorted-activities)})))
(fn [{:keys [db]} [{:keys [message requestId]}]]
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
activities (->> message
(transforms/json->clj)
(:activities)
(cske/transform-keys transforms/->kebab-case-keyword))
activities-indexed (zipmap (map activity-transaction-id activities)
activities)]
{:db (assoc-in db [:wallet :activities address] activities-indexed)})))
(def ^:private nested-merge (partial merge-with merge))
(rf/reg-event-fx
:wallet/activities-filtering-entries-updated
(fn [{:keys [db]} [{:keys [message requestId]}]]
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
activities (->> message
(transforms/json->clj)
(cske/transform-keys transforms/->kebab-case-keyword))
activities-indexed (zipmap (map activity-transaction-id activities)
activities)]
{:db (-> db
(update-in [:wallet :ui :activity-tab :request] dissoc requestId)
(update-in [:wallet :activities address] nested-merge activities-indexed))})))
@@ -11,31 +11,81 @@
(defn send-and-receive-activity
[{:keys [transaction relative-date status sender recipient token amount network-name
network-logo]}]
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :token
:token token
:amount amount}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}])
network-logo token-id nft-url nft-name]}]
(if token-id
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :collectible
:collectible nft-url
:collectible-name (if (> amount 1)
(str amount " " nft-name)
nft-name)
:collectible-number token-id}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}]
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :token
:token token
:amount amount}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}]))
;; WIP to add the mint activity.
;(defn mint-activity
; [{:keys [transaction relative-date status recipient network-name
; network-logo nft-name nft-url token-id]}]
; [quo/wallet-activity
; {:transaction transaction
; :timestamp relative-date
; :status status
; :counter 1
; :first-tag {:size 24
; :type :collectible
; :collectible nft-url
; :collectible-name nft-name
; :collectible-number token-id}
; :second-tag-prefix :t/at
; :second-tag {:type :address :address recipient}
; :third-tag-prefix :t/to
; :third-tag {:type :address :address recipient}
; :fourth-tag-prefix :t/via
; :fourth-tag {:size 24
; :type :network
; :network-name network-name
; :network-logo network-logo}
; :blur? false}])
(defn activity-item
[{:keys [transaction] :as activity}]
(case transaction
(:send :receive) [send-and-receive-activity activity]
;; WIP to add the mint activity.
;; :mint [mint-activity activity]
nil))
(defn view
@@ -172,17 +172,20 @@
(defn get-network-details
[chain-id]
(condp contains? chain-id
#{constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
constants/ethereum-sepolia-chain-id}
mainnet-network-details
(as-> chain-id $
(condp contains? $
#{constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
constants/ethereum-sepolia-chain-id}
mainnet-network-details
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
constants/arbitrum-sepolia-chain-id}
arbitrum-network-details
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
constants/arbitrum-sepolia-chain-id}
arbitrum-network-details
#{constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
#{constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
nil))
nil)
(when $
(assoc $ :chain-id chain-id))))
@@ -13,26 +13,26 @@
[utils.re-frame :as rf]))
(defn- on-disconnect
[wallet-account {:keys [name topic]}]
[wallet-account {:keys [name topic pairing-topic]}]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch
[:wallet-connect/disconnect-dapp
{:topic topic
:on-success (fn []
(rf/dispatch [:wallet-connect/remove-pairing-by-topic topic])
(rf/dispatch [:toasts/upsert
{:id :dapp-disconnect-success
:type :positive
:text (i18n/label :t/disconnect-dapp-success
{:dapp name
:account (:name wallet-account)})}]))
:on-fail (fn []
(rf/dispatch [:toasts/upsert
{:id :dapp-disconnect-failure
:type :negative
:text (i18n/label :t/disconnect-dapp-fail
{:dapp name
:account (:name wallet-account)})}]))}]))
{:topic topic
:pairing-topic pairing-topic
:on-success (fn []
(rf/dispatch [:toasts/upsert
{:id :dapp-disconnect-success
:type :positive
:text (i18n/label :t/disconnect-dapp-success
{:dapp name
:account (:name wallet-account)})}]))
:on-fail (fn []
(rf/dispatch [:toasts/upsert
{:id :dapp-disconnect-failure
:type :negative
:text (i18n/label :t/disconnect-dapp-fail
{:dapp name
:account (:name wallet-account)})}]))}]))
(defn- on-dapp-disconnect-press
[wallet-account dapp]
@@ -83,7 +83,8 @@
[]
(let [{:keys [bottom]} (safe-area/get-insets)
{:keys [color] :as wallet-account} (rf/sub [:wallet/current-viewing-account])
pairings (rf/sub [:wallet-connect/pairings])
sessions (rf/sub
[:wallet-connect/sessions-for-current-account])
theme (quo.theme/use-theme)]
[rn/view {:flex 1}
[header
@@ -91,7 +92,7 @@
:wallet-account wallet-account
:on-close #(rf/dispatch [:navigate-back])
:on-add #(rf/dispatch [:navigate-to :screen/wallet.scan-dapp])}]
(if (empty? pairings)
(if (empty? sessions)
[quo/empty-state
{:title (i18n/label :t/no-dapps)
:description (i18n/label :t/no-dapps-description)
@@ -99,16 +100,16 @@
:container-style style/empty-container-style}]
[rn/view (style/dapps-container bottom)
[rn/flat-list
{:data pairings
{:data sessions
:always-bounce-vertical false
:content-container-style (style/dapps-list theme)
:render-fn (fn [{:keys [topic]
{:keys [icons name url]} :peerMetadata}]
:render-fn (fn [{:keys [topic pairingTopic name url iconUrl]}]
[quo/dapp
{:dapp {:avatar (get icons 0)
:name name
:value url
:topic topic}
{:dapp {:avatar iconUrl
:name name
:value url
:topic topic
:pairing-topic pairingTopic}
:accessibility-label (str "dapp-" topic)
:state :default
:action :icon
@@ -187,15 +187,8 @@
(rf/reg-event-fx
:wallet/update-receiver-networks
(fn [{:keys [db]} [selected-networks]]
(let [amount (get-in db [:wallet :ui :send :amount])
disabled-from-chain-ids (get-in db [:wallet :ui :send :disabled-from-chain-ids])
filtered-disabled-from-chain-ids (filter (fn [chain-id]
(some #(= chain-id %)
selected-networks))
disabled-from-chain-ids)]
{:db (-> db
(assoc-in [:wallet :ui :send :receiver-networks] selected-networks)
(assoc-in [:wallet :ui :send :disabled-from-chain-ids] filtered-disabled-from-chain-ids))
(let [amount (get-in db [:wallet :ui :send :amount])]
{:db (assoc-in db [:wallet :ui :send :receiver-networks] selected-networks)
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]]})))
(rf/reg-event-fx
@@ -2,8 +2,19 @@
(:require
[cljs.test :refer-macros [is testing]]
[re-frame.db :as rf-db]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
status-im.contexts.wallet.send.events
[test-helpers.unit :as h]))
[status-im.contexts.wallet.send.utils :as send-utils]
[test-helpers.unit :as h]
[utils.money :as money]))
(defn collectible-with-balance
[balance]
{:name "DOG #1"
:description
"dogs are cute and this one is the cutestdogs are cute and this one is the cutest"
:ownership [{:address "0x01"
:balance balance}]})
(h/deftest-event :wallet/update-receiver-networks
[event-id dispatch]
@@ -12,19 +23,6 @@
selected-networks-after [:ethereum :optimism]
expected-db {:wallet {:ui {:send {:receiver-networks selected-networks-after}}}}]
(reset! rf-db/app-db {:wallet {:ui {:send {:receiver-networks selected-networks-before}}}})
(is (match? expected-db (:db (dispatch [event-id selected-networks-after]))))))
(testing "if receiver network removed, it is also removed from disabled ones"
(let [selected-networks-before [:ethereum :optimism :arbitrum]
selected-networks-after [:ethereum :optimism]
disabled-from-chain-ids-before [:optimism :arbitrum]
disabled-from-chain-ids-after [:optimism]
expected-db {:wallet {:ui {:send {:receiver-networks selected-networks-after
:disabled-from-chain-ids
disabled-from-chain-ids-after}}}}]
(reset! rf-db/app-db {:wallet {:ui {:send {:receiver-networks selected-networks-before
:disabled-from-chain-ids
disabled-from-chain-ids-before}}}})
(is (match? expected-db (:db (dispatch [event-id selected-networks-after])))))))
(h/deftest-event :wallet/set-token-to-send
@@ -163,3 +161,298 @@
result (dispatch [event-id {:amount amount}])]
(testing "amount set"
(is (match? amount (get-in result [:db :wallet :ui :send :amount]))))))
(h/deftest-event :wallet/clean-send-data
[event-id dispatch]
(let [token-symbol "ETH"
token {:symbol "ETH"
:name "Ether"
:networks #{{:chain-id 421614}
{:chain-id 11155420}
{:chain-id 11155111}}}
receiver-networks [421614 11155420]]
(reset! rf-db/app-db
{:wallet {:ui {:send {:token-display-name token-symbol
:token token
:receiver-networks receiver-networks}
:other-props :value}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui]) :send)))))
(h/deftest-event :wallet/select-address-tab
[event-id dispatch]
(let [expected-db {:wallet {:ui {:send {:select-address-tab "tab"}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send nil}}})
(is (match? expected-db (:db (dispatch [event-id "tab"]))))))
(h/deftest-event :wallet/clean-send-address
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:to-address "0x01"
:recipient {:recipient-type :saved-address
:label "label"}
:other-props :value}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :to-address)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :recipient)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/clean-send-amount
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:amount 10
:other-props :value}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/clean-disabled-from-networks
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:disabled-from-chain-ids [:optimism]
:other-props :value}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :disabled-from-chain-ids)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/clean-from-locked-amounts
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:from-locked-amounts "value"
:other-props :value}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :from-locked-amounts)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/disable-from-networks
[event-id dispatch]
(let [expected-db {:wallet {:ui {:send {:disabled-from-chain-ids [:optimism]
:other-props :value}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value}}}})
(is (match? expected-db (:db (dispatch [event-id [:optimism]]))))))
(h/deftest-event :wallet/unlock-from-amount
[event-id dispatch]
(let [expected-db {:wallet {:ui {:send {:other-props :value
:from-locked-amounts {}}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:from-locked-amounts {:chain-id [1 10]}}}}})
(is (match? expected-db (:db (dispatch [event-id :chain-id]))))))
(h/deftest-event :wallet/lock-from-amount
[event-id dispatch]
(let [expected-db {:wallet {:ui {:send {:other-props :value
:from-locked-amounts {:amount 10}}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value}}}})
(is (match? expected-db (:db (dispatch [event-id :amount 10]))))))
(h/deftest-event :wallet/clean-selected-token
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:token "ETH"
:token-display-name "ETH"
:tx-type :tx/collectible-erc-721}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :token)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :token-display-name)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :tx-type)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/clean-selected-collectible
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:collectible "ETH"
:token-display-name "ETH"
:amount 10}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :collectible)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :token-display-name)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/clean-suggested-routes
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send
{:other-props :value
:suggested-routes ["1" "2"]
:route "1"
:amount 10
:from-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:to-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:sender-network-values [:eth :arb1]
:receiver-network-values [:eth :arb1]
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false
:suggested-routes-call-timestamp ["1" "2"]}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :suggested-routes)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :route)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :from-values-by-chain)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :to-values-by-chain)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :sender-network-values)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :receiver-network-values)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :network-links)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:loading-suggested-routes?)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:suggested-routes-call-timestamp)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/suggested-routes-error
[event-id dispatch]
(let [sender-network-amounts [{:chain-id 1 :total-amount (money/bignumber "100") :type :loading}
{:chain-id 10 :total-amount (money/bignumber "200") :type :default}]
receiver-network-amounts [{:chain-id 1 :total-amount (money/bignumber "100") :type :loading}]
expected-result {:db {:wallet {:ui {:send
{:sender-network-values
(send-utils/reset-loading-network-amounts-to-zero
sender-network-amounts)
:receiver-network-values
(send-utils/reset-loading-network-amounts-to-zero
receiver-network-amounts)
:loading-suggested-routes? false
:suggested-routes {:best []}}}}}
:fx [[:dispatch
[:toasts/upsert
{:id :send-transaction-error
:type :negative
:text "error"}]]]}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:sender-network-values sender-network-amounts
:receiver-network-values receiver-network-amounts
:route :values
:loading-suggested-routes? true}}}})
(is (match? expected-result (dispatch [event-id {:message "error"}])))))
(h/deftest-event :wallet/reset-network-amounts-to-zero
[event-id dispatch]
(let [sender-network-values [{:chain-id 1 :total-amount (money/bignumber "100") :type :default}
{:chain-id 10 :total-amount (money/bignumber "200") :type :default}]
receiver-network-values [{:chain-id 1 :total-amount (money/bignumber "100") :type :loading}]
disabled-from-chain-ids [:ethereum]
sender-network-zero (send-utils/reset-network-amounts-to-zero
{:network-amounts sender-network-values
:disabled-chain-ids disabled-from-chain-ids})
receiver-network-zero (send-utils/reset-network-amounts-to-zero
{:network-amounts receiver-network-values
:disabled-chain-ids []})]
(testing "if sender-network-value and receiver-network-value are not empty"
(let [expected-db {:wallet {:ui {:send {:other-props :value
:sender-network-values sender-network-zero
:receiver-network-values receiver-network-zero}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]}}}})
(is (match? expected-db (:db (dispatch [event-id]))))))
(testing "if only receiver-network-value is empty"
(let [expected-db {:wallet {:ui {:send {:other-props :value
:sender-network-values sender-network-zero}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:sender-network-values sender-network-values
:receiver-network-values []
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]}}}})
(is (match? expected-db (:db (dispatch [event-id]))))))
(testing "if receiver-network-value and sender-network-values are empty"
(let [expected-db {:wallet {:ui {:send {:other-props :value}}}}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:sender-network-values []
:receiver-network-values []
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]}}}})
(is (match? expected-db (:db (dispatch [event-id]))))))))
(h/deftest-event :wallet/select-send-address
[event-id dispatch]
(let [address "eth:arb1:0x01"
prefix "eth:arb1:"
to-address "0x01"
recipient {:type :saved-address
:label "0x01...23f"}
stack-id :screen/wallet.select-address
start-flow? false
tx-type :tx/collectible-erc-721]
(testing "testing when collectible balance is more than 1"
(let [collectible (collectible-with-balance 2)
testnet-enabled? false
goerli-enabled? false
receiver-networks (network-utils/resolve-receiver-networks
{:prefix prefix
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
expected-result {:db {:wallet {:ui {:send {:other-props :value
:recipient recipient
:to-address to-address
:address-prefix prefix
:receiver-preferred-networks
receiver-networks
:receiver-networks receiver-networks
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:fx [nil
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?
:is-goerli-enabled? goerli-enabled?}})
(is (match? expected-result
(dispatch [event-id
{:address address
:recipient recipient
:stack-id stack-id
:start-flow? start-flow?}])))))
(testing "testing when collectible balance is 1"
(let [collectible (collectible-with-balance 1)
testnet-enabled? false
goerli-enabled? false
receiver-networks (network-utils/resolve-receiver-networks
{:prefix prefix
:testnet-enabled? testnet-enabled?
:goerli-enabled? goerli-enabled?})
expected-result {:db {:wallet {:ui {:send {:other-props :value
:recipient recipient
:to-address to-address
:address-prefix prefix
:receiver-preferred-networks
receiver-networks
:receiver-networks receiver-networks
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:fx [[:dispatch [:wallet/get-suggested-routes {:amount 1}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]}]
(reset! rf-db/app-db
{:wallet {:ui {:send {:other-props :value
:tx-type tx-type
:collectible collectible}}}
:profile/profile {:test-networks-enabled? testnet-enabled?
:is-goerli-enabled? goerli-enabled?}})
(is (match? expected-result
(dispatch [event-id
{:address address
:recipient recipient
:stack-id stack-id
:start-flow? start-flow?}])))))))
@@ -120,7 +120,7 @@
[]
[quo/alert-banner
{:action? true
:text (i18n/label :t/not-enough-assets)
:text (i18n/label :t/not-enough-assets-to-pay-gas-fees)
:button-text (i18n/label :t/buy-eth)
:on-button-press #(rf/dispatch [:show-bottom-sheet
{:content buy-token/view}])}])
@@ -154,11 +154,9 @@
[input-state set-input-state] (rn/use-state controlled-input/init-state)
[just-toggled-mode? set-just-toggled-mode?] (rn/use-state false)
clear-input! #(set-input-state controlled-input/delete-all)
handle-on-confirm (fn []
handle-on-confirm (fn [amount]
(rf/dispatch [:wallet/set-token-amount-to-send
{:amount
(controlled-input/input-value
input-state)
{:amount amount
:stack-id current-screen-id}]))
{fiat-currency :currency} (rf/sub [:profile/profile])
{token-symbol :symbol
@@ -157,7 +157,6 @@
[quo/data-item
{:container-style style/detail-item
:blur? false
:description :default
:card? false
:status :default
:size :small
@@ -1,8 +1,8 @@
(ns status-im.contexts.wallet.send.utils
(:require
[legacy.status-im.utils.hex :as utils.hex]
[native-module.core :as native-module]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[utils.hex :as utils.hex]
[utils.money :as money]))
(defn amount-in-hex
+35 -18
View File
@@ -23,22 +23,39 @@
:block-number blockNumber
:accounts accounts})
(case event-type
"pending-transaction-status-changed" {:fx
[[:dispatch
[:wallet/pending-transaction-status-changed-received
(transforms/js->clj event-js)]]]}
"wallet-owned-collectibles-filtering-done" {:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done
(transforms/js->clj event-js)]]]}
"wallet-get-collectibles-details-done" {:fx [[:dispatch
[:wallet/get-collectible-details-done
(transforms/js->clj event-js)]]]}
"wallet-tick-reload" {:fx [[:dispatch [:wallet/reload]]]}
"wallet-blockchain-status-changed" {:fx [[:dispatch
[:wallet/blockchain-status-changed
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-done" {:fx
[[:dispatch
[:wallet/activity-filtering-for-current-account-done
(transforms/js->clj event-js)]]]}
"pending-transaction-status-changed"
{:fx
[[:dispatch
[:wallet/pending-transaction-status-changed-received
(transforms/js->clj event-js)]]]}
"wallet-owned-collectibles-filtering-done"
{:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done
(transforms/js->clj event-js)]]]}
"wallet-get-collectibles-details-done"
{:fx [[:dispatch
[:wallet/get-collectible-details-done
(transforms/js->clj event-js)]]]}
"wallet-tick-reload"
{:fx [[:dispatch [:wallet/reload]]]}
"wallet-blockchain-status-changed"
{:fx [[:dispatch
[:wallet/blockchain-status-changed
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-done"
{:fx
[[:dispatch
[:wallet/activity-filtering-for-current-account-done
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-entries-updated"
{:fx [[:dispatch
[:wallet/activities-filtering-entries-updated
(transforms/js->clj event-js)]]]}
(log/debug ::unknown-wallet-event :type event-type)))))
@@ -85,12 +85,45 @@
(defn required-networks-supported?
[proposal supported-networks]
(let [required-networks (get-in proposal [:params :requiredNamespaces :eip155 :chains])
supported-eip155 (set (map chain-id->eip155 supported-networks))]
(every? #(contains? supported-eip155 %) required-networks)))
(let [supported-namespaces #{:eip155}
required-namespaces (get-in proposal [:params :requiredNamespaces])]
(when (every? #(contains? supported-namespaces %)
(keys required-namespaces))
(let [required-networks (get-in required-namespaces [:eip155 :chains])
supported-eip155 (set (map chain-id->eip155 supported-networks))]
(every? #(contains? supported-eip155 %)
required-networks)))))
(defn get-networks-by-mode
[db]
(let [test-mode? (get-in db [:profile/profile :test-networks-enabled?])
networks (get-in db [:wallet :networks (if test-mode? :test :prod)])]
(mapv #(-> % :chain-id) networks)))
(defn add-full-testnet-name
"Updates the `:full-name` key with the full testnet name if using testnet `:chain-id`.\n
e.g. `{:full-name \"Mainnet\"}` -> `{:full-name \"Mainnet Sepolia\"`}`"
[network]
(let [add-testnet-name (fn [testnet-name]
(update network :full-name #(str % " " testnet-name)))]
(condp #(contains? %1 %2) (:chain-id network)
constants/sepolia-chain-ids (add-testnet-name constants/sepolia-full-name)
constants/goerli-chain-ids (add-testnet-name constants/goerli-full-name)
network)))
(defn event-should-be-handled?
[db {:keys [topic]}]
(some #(= topic %)
(map :topic (:wallet-connect/sessions db))))
(defn sdk-session->db-session
[{:keys [topic expiry pairingTopic] :as session}]
{:topic topic
:expiry expiry
:sessionJson (transforms/clj->json session)
:pairingTopic pairingTopic
:name (get-in session [:peer :metadata :name])
:iconUrl (get-in session [:peer :metadata :icons 0])
:url (get-in session [:peer :metadata :url])
:accounts (get-in session [:namespaces :eip155 :accounts])
:disconnected false})
@@ -1,17 +1,14 @@
(ns status-im.contexts.wallet.wallet-connect.effects
(:require
[cljs-bean.core :as bean]
[native-module.core :as native-module]
[promesa.core :as promesa]
[re-frame.core :as rf]
[react-native.wallet-connect :as wallet-connect]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
[status-im.contexts.wallet.wallet-connect.signing :as signing]
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
[utils.i18n :as i18n]
[utils.security.core :as security]
[utils.transforms :as transforms]))
[utils.security.core :as security]))
(rf/reg-fx
:effects.wallet-connect/init
@@ -34,13 +31,6 @@
:event wc-event
:handler handler})))
(rf/reg-fx
:effects.wallet-connect/fetch-pairings
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-pairings web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/pair
(fn [{:keys [web3-wallet url on-success on-fail]}]
@@ -56,13 +46,6 @@
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/fetch-active-sessions
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-active-sessions web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/approve-session
(fn [{:keys [web3-wallet proposal supported-namespaces on-success on-fail]}]
@@ -77,38 +60,68 @@
(promesa/then on-success)
(promesa/catch on-fail)))))
(rf/reg-fx
:effects.wallet-connect/fetch-active-sessions
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-active-sessions web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/sign-message
(fn [{:keys [password address data on-success on-error]}]
(-> {:data data
:account address
:password (security/safe-unmask-data password)}
bean/->js
transforms/clj->json
native-module/sign-message
(promesa/then wallet-connect-core/extract-native-call-signature)
(fn [{:keys [password address data rpc-method on-success on-error]}]
(let [password (security/safe-unmask-data password)]
(-> (condp =
rpc-method
:personal-sign
(signing/personal-sign password address data)
:eth-sign
(signing/eth-sign password address data)
(signing/personal-sign password address data))
(promesa/then on-success)
(promesa/catch on-error)))))
(rf/reg-fx
:effects.wallet-connect/prepare-transaction
(fn [{:keys [tx chain-id on-success on-error]}]
(-> (transactions/prepare-transaction tx
chain-id
transactions/default-tx-priority)
(promesa/then on-success)
(promesa/catch on-error))))
(rf/reg-fx
:effects.wallet-connect/sign-transaction
(fn [{:keys [password address chain-id tx on-success on-error]}]
(-> (transactions/sign-transaction (security/safe-unmask-data password) address tx chain-id)
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
(-> (transactions/sign-transaction (security/safe-unmask-data password)
address
tx-hash
tx-args
chain-id)
(promesa/then on-success)
(promesa/catch on-error))))
(rf/reg-fx
:effects.wallet-connect/send-transaction
(fn [{:keys [password address chain-id tx on-success on-error]}]
(-> (transactions/send-transaction (security/safe-unmask-data password) address tx chain-id)
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
(-> (transactions/send-transaction (security/safe-unmask-data password)
address
tx-hash
tx-args
chain-id)
(promesa/then on-success)
(promesa/catch on-error))))
(rf/reg-fx
:effects.wallet-connect/sign-typed-data
(fn [{:keys [password address data version on-success on-error]}]
(-> (wallet-connect-core/sign-typed-data version data address (security/safe-unmask-data password))
(promesa/then wallet-connect-core/extract-native-call-signature)
(fn [{:keys [password address data version chain-id on-success on-error]}]
(-> (signing/eth-sign-typed-data (security/safe-unmask-data password)
address
data
chain-id
version)
(promesa/then on-success)
(promesa/catch on-error))))
@@ -8,7 +8,8 @@
status-im.contexts.wallet.wallet-connect.responding-events
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
[taoensso.timbre :as log]
[utils.i18n :as i18n]))
[utils.i18n :as i18n]
[utils.transforms :as types]))
(rf/reg-event-fx
:wallet-connect/init
@@ -22,12 +23,7 @@
(fn [{:keys [db]} [web3-wallet]]
{:db (assoc db :wallet-connect/web3-wallet web3-wallet)
:fx [[:dispatch [:wallet-connect/register-event-listeners]]
[:effects.wallet-connect/fetch-pairings
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get dApp pairings" {:error %})
:on-success (fn [data]
(rf/dispatch [:wallet-connect/set-pairings
(js->clj data :keywordize-keys true)]))}]]}))
[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))
(rf/reg-event-fx
:wallet-connect/register-event-listeners
@@ -40,7 +36,11 @@
[:effects.wallet-connect/register-event-listener
[web3-wallet
constants/wallet-connect-session-request-event
#(rf/dispatch [:wallet-connect/on-session-request %])]]]})))
#(rf/dispatch [:wallet-connect/on-session-request %])]]
[:effects.wallet-connect/register-event-listener
[web3-wallet
constants/wallet-connect-session-delete-event
#(rf/dispatch [:wallet-connect/on-session-delete %])]]]})))
(rf/reg-event-fx
:wallet-connect/on-init-fail
@@ -54,20 +54,24 @@
(fn [{:keys [db]} [proposal]]
(log/info "Received Wallet Connect session proposal: " {:id (:id proposal)})
(let [accounts (get-in db [:wallet :accounts])
without-watched (remove :watch-only? (vals accounts))
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
available-accounts (filter #(and (:operable? %)
(not (:watch-only? %)))
(vals accounts))
networks (wallet-connect-core/get-networks-by-mode db)
session-networks (wallet-connect-core/proposal-networks-intersection proposal
networks)
required-networks-supported? (wallet-connect-core/required-networks-supported? proposal
networks)]
(if required-networks-supported?
(if (and (not-empty session-networks) required-networks-supported?)
{:db (update db
:wallet-connect/current-proposal assoc
:request proposal
:session-networks session-networks
:address (-> without-watched
first
:address))
:address (or current-viewing-address
(-> available-accounts
first
:address)))
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
@@ -85,9 +89,16 @@
(rf/reg-event-fx
:wallet-connect/on-session-request
(fn [_ [event]]
(log/info "Received Wallet Connect session request: " event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}))
(fn [{:keys [db]} [event]]
(when (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-delete
(fn [{:keys [db]} [{:keys [topic] :as event}]]
(when (wallet-connect-core/event-should-be-handled? db event)
(log/info "Received Wallet Connect session delete: " event)
{:fx [[:dispatch [:wallet-connect/disconnect-session topic]]]})))
(rf/reg-event-fx
:wallet-connect/reset-current-session-proposal
@@ -104,28 +115,18 @@
(fn [{:keys [db]}]
{:db (dissoc db :wallet-connect/current-request)}))
(rf/reg-event-fx
:wallet-connect/set-pairings
(fn [{:keys [db]} [pairings]]
{:db (assoc db :wallet-connect/pairings pairings)}))
(rf/reg-event-fx
:wallet-connect/remove-pairing-by-topic
(fn [{:keys [db]} [topic]]
{:db (update db
:wallet-connect/pairings
(fn [pairings]
(remove #(= (:topic %) topic) pairings)))}))
(rf/reg-event-fx
:wallet-connect/disconnect-dapp
(fn [{:keys [db]} [{:keys [topic on-success on-fail]}]]
(fn [{:keys [db]} [{:keys [pairing-topic on-success on-fail]}]]
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/disconnect
{:web3-wallet web3-wallet
:topic topic
:topic pairing-topic
:on-fail on-fail
:on-success on-success}]]})))
:on-success (fn []
(rf/dispatch [:wallet-connect/disconnect-session pairing-topic])
(when on-success
(on-success)))}]]})))
(rf/reg-event-fx
:wallet-connect/pair
@@ -137,15 +138,6 @@
:on-fail #(log/error "Failed to pair with dApp" {:error %})
:on-success #(log/info "dApp paired successfully")}]]})))
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions
(fn [{:keys [db]}]
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/fetch-active-sessions
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get active sessions" {:error %})
:on-success #(log/info "Got active sessions successfully" {:sessions %})}]]})))
(rf/reg-event-fx
:wallet-connect/approve-session
(fn [{:keys [db]}]
@@ -204,10 +196,55 @@
{:version version}))}]]]}
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
;; then replace the list we have stored in the database with the one that came from the SDK.
;; In addition to that, we also update the backend state by marking sessions that are not
;; active anymore by calling `:wallet-connect/disconnect-session`.
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions-success
(fn [{:keys [db now]} [sessions]]
(let [persisted-sessions (:wallet-connect/sessions db)
sessions (->> (js->clj sessions :keywordize-keys true)
vals
(map wallet-connect-core/sdk-session->db-session))
expired-sessions (remove
(fn [{:keys [expiry]}]
(> expiry (/ now 1000)))
persisted-sessions)]
{:fx (mapv (fn [{:keys [pairingTopic]}]
[:wallet-connect/disconnect-session pairingTopic])
expired-sessions)
:db (assoc db :wallet-connect/sessions sessions)})))
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions
(fn [{:keys [db]}]
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/fetch-active-sessions
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get active sessions" {:error %})
:on-success #(rf/dispatch [:wallet-connect/fetch-active-sessions-success %])}]]})))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions-success
(fn [{:keys [db]} [sessions]]
{:db (assoc db :wallet-connect/persisted-sessions sessions)}))
(let [sessions' (mapv (fn [{:keys [sessionJson] :as session}]
(assoc session
:accounts
(-> sessionJson
types/json->clj
:namespaces
:eip155
:accounts)))
sessions)]
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]
:db (assoc db :wallet-connect/sessions sessions')})))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions-fail
(fn [_ [error]]
(log/info "Wallet Connect fetch persisted sessions failed" error)
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]}))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions
@@ -218,7 +255,7 @@
;; 0 means, return everything
:params [0]
:on-success [:wallet-connect/fetch-persisted-sessions-success]
:on-error #(log/info "Wallet Connect fetch persisted sessions failed" %)}]]]}))
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]}))
(rf/reg-event-fx
:wallet-connect/persist-session
@@ -226,5 +263,22 @@
{:fx [[:json-rpc/call
[{:method "wallet_addWalletConnectSession"
:params [(js/JSON.stringify session-info)]
:on-success #(log/info "Wallet Connect session persisted")
:on-success (fn []
(log/info "Wallet Connect session persisted")
(rf/dispatch [:wallet-connect/fetch-persisted-sessions]))
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
(rf/reg-event-fx
:wallet-connect/disconnect-session
(fn [{:keys [db]} [pairing-topic]]
{:db (update db
:wallet-connect/sessions
(fn [sessions]
(->> sessions
(remove #(= (:pairingTopic %) pairing-topic))
(into []))))
:fx [[:json-rpc/call
[{:method "wallet_disconnectWalletConnectSession"
:params [pairing-topic]
:on-success #(log/info "Wallet Connect session disconnected")
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))

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