Compare commits

...
Author SHA1 Message Date
Prem Chaitanya Prathi 534974175c chore: set lightClient as default 2024-07-01 11:58:10 +05:30
Prem Chaitanya Prathi 62cec06532 feat: statusgo filter optimizations 2024-07-01 11:54:40 +05:30
yqrashawn 0d9bedf11c fix: use "Biometric" instead of Touch ID when no Biometric found (#20555)
Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-07-01 09:57:21 +08:00
Volodymyr Kozieiev 3e268936f6 Disable input field on send asset page (#20564) 2024-06-28 13:27:38 +01:00
Parvesh Monu e92da6d24b fix can't enter channel after community is fetched for the first time (#20508) 2024-06-28 16:36:34 +05:30
Andrea Maria Piana 34c95c42d1 Fix member list in community channels
https://github.com/status-im/status-go/compare/e0673ad1...6e056348
2024-06-27 19:48:28 +01:00
mmilad75 1ee44259c4 Wallet - Resolve user types on Transaction Confirmation Page #20267 (#20480) 2024-06-27 18:12:59 +02:00
Parvesh Monu 112b69c1d6 fix ios wrong status bar color in dark theme (#20540) 2024-06-27 20:23:51 +05:30
Ulises Manuel 3ce6a86e9b fix(wallet): Account derivation for added keypairs (#20536)
* Fix color of non-selected keypairs

* Fix pressable area in keypairs

* Make validation more robust

* Make confirm button always pressable

* Fix wrong sentence in errors

* Solve account creation by fixing a memoized callback

* Improve logging
2024-06-26 12:10:16 -06:00
Mohsen b005eb8181 feat!: add saved addresses to wallet settings (#20475) 2024-06-26 16:44:29 +03:30
Volodymyr Kozieiev 4bd7abaace Added tests for wallet send events (#20547) 2024-06-26 14:02:55 +01:00
Alexander e2e8afb7b1 WC signing/sending transactions flow (#20445)
* WC signing transactions flow

* Fixes

* Fixes

* Post-review fixes

* Removed leftover

* Post-review fixes

* Fixes

* Fixes

* Test fixes
2024-06-26 14:45:43 +02:00
Sean Hagstrom 256f3f8f24 feat!: add key pairs and accounts settings to wallet settings (#20464)
* tweak: use support blur colors for action drawer icons

* tweak: support blur colors for drawer-top icon

* tweak: support blur colors for account list inside keypair component

* tweak: use blur colors for missing-keypair bottom sheet actions

* feat: remove feature-flag for key-pairs and accounts inside wallet settings

* fix: ensure key-pairs-and-accounts settings are visible

* tweak: display key-pair rename screen as full-screen modal

* tweak: animate key-pair scanning screen as modal

* fix: do not allow user to rename key-pair to an existing key-pair name

* fix: ensure we visualise the validation error for key-pair name that is too long

* fix: ensure we can see the recovery-phrase suggestions when testnet-mode is active

* tweak: show recovery-phrase errors when keyboard is hidden

* fix: ensure we do not re-hash password

* fix: ensure we call `on-close` function when successfully handling biometrics auth

* fix: ensure we clear error states when editing the recovery-phrase input

* fix: use blur styles for standard authentication password input

* chore: add labels for qr validation

* tweak: handle display import-qr error and allow for re-scanning

* tweak: update blur background for all bottom-sheets

* chore: add feature-flag for import-all key-pairs button for missing key-pairs

* tidy: remove unused variable

* fix: ensure layout for android is correct when entering seed-phrase in testnet-mode

* fix: ensure we return the updated db when updating the db with backup key-pair

* tweak: coerce nil to empty string

* tweak: change validation error message for short key-pair name

* tweak: hide the options icon for the default key-pair inside key-pairs and accounts settings
2024-06-26 13:16:00 +01:00
Jamie Caprani 6931fd0052 chore(wallet/shell): minor fixes from design review (#20494)
* chore(wallet): make recent tab fullscreen for empty view

* chore(wallet): hide advanced button on send page

* chore(wallet): hide estimated fees when no routes found

* chore(wallet): update emoji icon to edit

* chore(wallet): update key pair placeholder to use keypair example

* chore(shell): feature flag saved address option in scanner
2024-06-26 02:05:19 -07:00
Yevheniia Berdnyk 136c3c0032 e2e: fixed KeyError for missed SauceLabs session id 2024-06-26 00:03:50 +03:00
Tetiana Churikova a92b50afea .github: add default prio label for bug (#20557) 2024-06-25 17:35:08 +02:00
Jamie Caprani fd3a21a320 fix(wallet): native share should point to opensea link (#20222) 2024-06-25 07:56:11 -07:00
Lungu Cristian f93e372d18 Add data-item to quo/category (#20542)
* feat: added data-item to category quo component

* feat: session proposal with data-item & category

* test: category with data-items

* chore: removed unnecessary ->

* fix: trailing newline
2024-06-25 15:35:45 +03:00
Parvesh Monu 0ed39a42ef fix "Remove from contacts" is available when the user is not your contact (#20541) 2024-06-25 13:48:53 +05:30
yqrashawnandYevheniia Berdnyk ead51b7e7c feat: simplification of onboarding intro view (#20386)
* feat: simplification of onboarding intro view

Signed-off-by: yqrashawn <namy.19@gmail.com>

* feat: new onboarding illustration

* fix: add accessibility label

* fix: wrong navigation stack

Signed-off-by: yqrashawn <namy.19@gmail.com>

* e2e: updated sign in

* fix: onboarding nav stack after flow change

---------

Signed-off-by: yqrashawn <namy.19@gmail.com>
Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-06-25 11:03:10 +08:00
Icaro Motta 9481890624 fix(profile)_: Truncate profile name in settings screen (#20483)
After migrating from v1 to v2, some user names may be too long to fit in some
devices in the "Settings > Edit Profile > Name" setting. The solution was to
truncate in the UI the name to the max valid length in v2, which is 20
characters.

Other small improvements:

- Don't use entire Clojure maps as the :key in React. This is known to be slow
  because it's expensive for Clojure to generally transform a data structure
  into its string representation.
- Don't find the last item of a list using last and an equality between two
  maps. This will force each iteration to call last, which in turn will iterate
  over the entire list of items (we can think of the Clojure lazy seq as a
  linked list). Instead, we now cache the index outside the loop and do a number
  comparison.
- Don't pass entire props to style functions when not needed because
  destructuring has a cost. I wouldn't personally worry about this 99% of the
  time, but when there's only argument like in this PR where we were passing a
  single blur? argument, it's preferable to not use a map.
2024-06-24 20:08:23 -03:00
Icaro Motta 419e84db08 chore(tests)_: Make bignumber instances test friendly (#20535)
Solves a problem encountered in unit tests, where instances of BigNumber (used
in the utils.money namespace) can't be compared with = or match?

If you try the following code you will always get false because they're
different instances in memory.

  (= (money/bignumber 0) (money/bignumber 0))

We now extend BigNumber (from lib bignumber.js) so that their instances are
comparable (e.g. necessary to sort) and understand equality.

We also extend BigNumber to work with the match? directive. For example, this is
the output of comparing a nested map containing bignumbers (colored in the
terminal):

  (match? {:a {:b {:c (money/bignumber 42)}}}
          {:a {:b {:c (money/bignumber 43)}}})

FAIL in (equivalence-test) (at cljs$test$run_block (status-mobile/target/test/cljs-runtime/cljs.test.js:366:13)
expected: (match? {:a {:b {:c (money/bignumber 42)}}} {:a {:b {:c (money/bignumber 43)}}})
  actual: {:a
 {:b {:c (mismatch (expected "42") (actual "43"))}}}
2024-06-24 15:56:55 -03:00
Icaro Motta 66785d01ec chore(perf)_: Use optimized endpoint to get communities (#20481)
Adapts the client code to use the new optimized endpoint to get communities with
images pointing to the media server. Related status-go PR
https://github.com/status-im/status-go/pull/5336.
2024-06-24 09:45:03 -03:00
Andrea Maria Piana 1cc4807336 chore_: add make targets for tail/pull geth.log 2024-06-24 11:19:23 +01:00
Parvesh Monu 141252e5a0 fix no request for permission for push notifications when you enable them in app settings (#20531) 2024-06-24 15:12:03 +05:30
Yevheniia Berdnyk 9d825ee04e e2e: update for wallet users and community links test 2024-06-21 18:25:49 +03:00
Mohamed Javid fb84f105db chore(wallet): refactor keypairs data in app-db (#20469)
This commit refactors the keypairs data in app-db to save them by indexed by key-uid which will help to fetch, update, and delete easily instead of using filter and some methods every time we need to perform those operations.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-06-21 20:47:26 +05:30
flexsurfer f509d132f3 Allow non admin to add members to group chats #20396 (#20428) 2024-06-21 15:49:20 +02:00
Parvesh Monu 5ee5d70567 Show correct drawer message for pending community request (#20485) 2024-06-21 17:20:20 +05:30
jakub b5a09a334a Include process of status-go PR
Define a process for status-go PR as more of those are expected to be
opened by the Waku team.

Specify that testing is mandatory before merge
2024-06-21 07:46:16 +01:00
163 changed files with 2504 additions and 1363 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
name: MVPBug Report
about: MVPBug Report
title: ''
labels: 'E:Mobile Bug MVP'
labels: ['E:Mobile Bug MVP', ':1234: low prio']
assignees: ''
---
+16
View File
@@ -70,3 +70,19 @@ Documentation change PR (review please): https://github.com/status-im/status.im/
| Please embed Image/Video here of the before and after. | Please embed Image/Video here of the before and after. | Please embed Image/Video here of the before and after. |
status: ready <!-- Can be ready or wip -->
<!-- Uncomment this section for status-go upgrade/dogfooding pull requests
- Specify potentially impacted user flows in _Areas that maybe impacted*.
- Ensure that _Steps to test_ is filled in.
### Risk
Described potential risks and worst case scenarios.
Tick **one**:
- [ ] Low risk: 2 devs MUST perform testing as specified above and attach their results as comments to this PR **before** merging.
- [ ] High risk: QA team MUST perform additional testing in the specified affected areas **before** merging.
-->
+10
View File
@@ -447,6 +447,16 @@ android-devices: export TARGET := android-sdk
android-devices: ##@other Invoke adb devices
adb devices
android-pull-geth: export TARGET := android-sdk
android-pull-geth: export VERSION ?= debug
android-pull-geth:
adb pull "/storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log"
android-tail-geth: export TARGET := android-sdk
android-tail-geth: export VERSION ?= debug
android-tail-geth:
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-logcat: export TARGET := android-sdk
android-logcat: ##@other Read status-mobile logs from Android phone using adb
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
+1 -3
View File
@@ -119,8 +119,6 @@
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
@@ -133,7 +131,7 @@
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<true/>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A00000080400010101</string>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

+2 -1
View File
@@ -131,7 +131,8 @@
:output-dir "target/test"
:optimizations :simple
:target :node-test
:dev {:devtools {:preloads [status-im.setup.schema-preload]}}
:dev {:devtools {:preloads [status-im.setup.schema-preload
status-im.setup.test-preload]}}
;; Uncomment line below to `make test-watch` a specific file
:ns-regexp #shadow/env "SHADOW_NS_REGEXP"
:main legacy.status-im.test-runner/main
+3 -1
View File
@@ -38,10 +38,12 @@
:always
(update :contacts conj (:id member))))
(defn community-chat-id->channel-id [chat-id] (subs chat-id constants/community-id-length))
(defn decode-chat-id
[chat-id]
(let [community-id (subs chat-id 0 constants/community-id-length)
channel-id (subs chat-id constants/community-id-length)]
channel-id (community-chat-id->channel-id chat-id)]
{:community-id community-id
:channel-id channel-id}))
+2 -1
View File
@@ -135,7 +135,8 @@
(>= (- now app-in-background-since)
constants/ms-in-bg-for-require-bioauth))]
(rf/merge cofx
{:db (dissoc db :app-in-background-since)}
{:db (dissoc db :app-in-background-since)
:effects.biometric/get-supported-type nil}
(mailserver/process-next-messages-request)
(when-not new-account?
(universal-links/process-stored-event))
@@ -28,7 +28,7 @@
[{:keys [db] :as cofx} {:keys [auth-method logout?]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
(rf/merge cofx
{:set-root :progress
{:dispatch [:init-root :progress]
:effects.shell/reset-state nil
:hide-popover nil
::logout nil
@@ -6,6 +6,7 @@
[legacy.status-im.ui.components.react :as react]
[quo.core :as quo]
[react-native.platform :as platform]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -57,7 +58,15 @@
:accessibility-label :local-notifications-settings-button
:subtitle (i18n/label :t/local-notifications-subtitle)
:active notifications-enabled?
:on-press #(rf/dispatch [:push-notifications/switch (not notifications-enabled?)])
:on-press (fn []
(when-not notifications-enabled?
(rf/dispatch
[:request-permissions
{:permissions [:post-notifications]
:on-allowed #(log/info "push notification permissions were allowed")
:on-denied #(log/error
"user denied push notification permissions")}]))
(rf/dispatch [:push-notifications/switch (not notifications-enabled?)]))
:accessory :switch}]]))
(defn notifications-settings
+2 -1
View File
@@ -53,7 +53,8 @@
[]
[;;PROGRESS
{:name :progress
:options {:insets {:top? true}}
:options {:insets {:top? true}
:theme :dark}
:component progress/progress}
;;COMMUNITY
@@ -14,9 +14,7 @@
[react-native.reanimated :as reanimated]))
(defn drag-gesture
[x-pos disabled? track-width sliding-complete?
set-sliding-complete
on-complete reset-fn]
[x-pos disabled? track-width sliding-complete? set-sliding-complete on-complete reset-fn]
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled (not disabled?))
@@ -71,14 +69,16 @@
(dimensions :thumb))
[dimensions])
custom-color (if (= type :danger) :danger customization-color)
gesture (rn/use-memo #(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn)
[sliding-complete? disabled?])]
gesture (rn/use-memo
(fn []
(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn))
[sliding-complete? disabled? on-complete])]
[gesture/gesture-detector
{:gesture gesture}
[reanimated/view
@@ -8,10 +8,11 @@
[react-native.core :as rn]))
(defn- get-icon-color
[danger? theme]
(if danger?
(colors/theme-colors colors/danger-50 colors/danger-60 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
[blur? danger? theme]
(cond
danger? (colors/theme-colors colors/danger-50 colors/danger-60 theme)
blur? colors/white-opa-70
:else (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn- divider
[theme blur?]
@@ -51,7 +52,7 @@
:accessible true
:style (style/left-icon sub-label)}
[icon/icon icon
{:color (or icon-color (get-icon-color danger? theme))
{:color (or icon-color (get-icon-color blur? danger? theme))
:no-color no-icon-color?
:size 20}]])
[rn/view
@@ -84,7 +85,7 @@
:accessible true
:accessibility-label :right-icon-for-action}
[icon/icon right-icon
{:color (get-icon-color danger? theme)
{:color (get-icon-color blur? danger? theme)
:size 20}]])
(when (= state :selected)
[rn/view {:style style/right-icon}
@@ -20,8 +20,9 @@
{:background-color (when-not (or scroll? blur?)
(colors/theme-colors colors/white colors/neutral-95 theme))})
(def buttons-container
{:flex-direction :row
(defn buttons-container
[actions]
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
@@ -17,9 +17,9 @@
[:catn
[:props
[:map {:closed true}
[:actions [:maybe [:enum :one-action :two-actions]]]
[:actions [:maybe [:enum :one-action :two-actions :two-vertical-actions]]]
[:description {:optional true} [:maybe [:enum :top :bottom :top-error]]]
[:description-text {:optional true} [:maybe :string]]
[:description-text {:optional true} [:maybe [:or :string :schema.common/hiccup]]]
[:description-top-text {:optional true} [:maybe :string]]
[:error-message {:optional true} [:maybe :string]]
[:role {:optional true} [:maybe [:enum :admin :member :token-master :owner]]]
@@ -72,8 +72,9 @@
:context (i18n/label (keyword "t" role))}
context-tag-props)]])
[rn/view {:style style/buttons-container}
(when (= actions :two-actions)
[rn/view {:style (style/buttons-container actions)}
(when (or (= actions :two-actions)
(= actions :two-vertical-actions))
[button/button
(merge
{:size 40
@@ -93,8 +94,10 @@
button-one-props)
button-one-label]]
(when (= description :bottom)
[text/text
{:size :paragraph-2
:style (style/description-bottom scroll? blur? theme)} description-text])]))
(if (string? description-text)
[text/text
{:size :paragraph-2
:style (style/description-bottom scroll? blur? theme)} description-text]
description-text))]))
(def view (schema/instrument #'view-internal ?schema))
@@ -18,7 +18,7 @@
(defn- left-image
[{:keys [type customization-color account-avatar-emoji account-avatar-type icon-avatar
profile-picture]}]
profile-picture blur?]}]
(case type
:account [account-avatar/view
{:customization-color customization-color
@@ -28,6 +28,7 @@
:keypair [icon-avatar/icon-avatar
{:icon icon-avatar
:border? true
:blur? blur?
:color :neutral}]
:default-keypair [user-avatar/user-avatar
@@ -213,6 +214,7 @@
[rn/view {:style style/left-container}
[left-image
{:type type
:blur? blur?
:customization-color customization-color
:account-avatar-emoji account-avatar-emoji
:account-avatar-type account-avatar-type
@@ -31,7 +31,8 @@
:size :paragraph-2}
(:name account-props)]
[address-text/view
{:networks networks
{:blur? blur?
:networks networks
:address (:address account-props)
:format :short}]]]
(when (= action :icon)
@@ -34,7 +34,8 @@
(def container-info
{:flex-direction :row
:align-items :center})
:align-items :center
:flex 1})
(def user-info
{:margin-left 8})
+8 -6
View File
@@ -25,14 +25,16 @@
:style {:width 32 :height 32}}]
[rn/view {:style style/user-info}
[text/text
{:weight :semi-bold
:size :paragraph-1
:style (style/style-text-name theme)}
{:weight :semi-bold
:size :paragraph-1
:number-of-lines 1
:style (style/style-text-name theme)}
(:name dapp)]
[text/text
{:weight :regular
:size :paragraph-2
:style (style/style-text-value theme)}
{:weight :regular
:size :paragraph-2
:number-of-lines 1
:style (style/style-text-value theme)}
(:value dapp)]]]
(when right-component
[right-component dapp])]))
@@ -31,7 +31,7 @@
(defn- checkbox-border-unchecked-color
[theme]
{:normal (colors/theme-colors colors/neutral-30 colors/neutral-70 theme)
:blur (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-40 theme)})
:blur (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)})
(defn- filled-checkbox-background-color
[theme]
@@ -51,3 +51,24 @@
:right-icon :i/globe
:chevron? true}]}])
(h/is-truthy (h/get-by-text "subtitle"))))
(h/describe "Data Item Category tests"
(h/test "category renders"
(h/render [category/category
{:list-type :data-item
:label "Label"
:data [{:title "Item 1"
:subtitle "subtitle"
:right-icon :i/globe}]}])
(h/is-truthy (h/get-by-text "Label"))
(h/is-truthy (h/get-by-text "Item 1"))
(h/is-truthy (h/get-by-text "subtitle")))
(h/test "category renders without label"
(h/render [category/category
{:list-type :data-item
:data [{:title "Item 1"
:subtitle "subtitle"
:right-icon :i/globe}]}])
(h/is-falsy (h/query-by-label-text "Label"))
(h/is-truthy (h/get-by-text "Item 1"))))
@@ -0,0 +1,32 @@
(ns quo.components.settings.category.data-item.view
(:require
[quo.components.markdown.text :as text]
[quo.components.settings.category.style :as style]
[quo.components.settings.data-item.view :as data-item]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn view
[{:keys [label data container-style blur?]}]
(let [theme (quo.theme/use-theme)
last-item (rn/use-memo #(last data) [data])]
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
:size :paragraph-2
:style (style/label blur? theme)}
label])
[rn/view {:style (style/settings-items blur? theme)}
(for [item data
;; NOTE: overwriting the background of the data-item in favor of the category bg
:let [data-item-container-style (-> item :container-style (assoc :background-color nil))
data-item-props (assoc item
:blur? blur?
:container-style data-item-container-style)]]
^{:key item}
[:<>
[data-item/view data-item-props]
(when-not (= item last-item)
[rn/view {:style (style/settings-separator blur? theme)}])])]]))
@@ -7,20 +7,23 @@
[react-native.core :as rn]))
(defn settings-category
[{:keys [label data container-style] :as props}]
(let [theme (quo.theme/use-theme)
settings-item (filter identity data)]
[{:keys [label data blur? container-style]}]
(let [theme (quo.theme/use-theme)
settings-items (remove nil? data)
last-index (dec (count settings-items))]
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
:size :paragraph-2
:style (style/label props theme)}
:style (style/label blur? theme)}
label])
[rn/view {:style (style/settings-items props theme)}
(for [item settings-item]
^{:key item}
[:<>
[settings-item/view item]
(when-not (= item (last settings-item))
[rn/view {:style (style/settings-separator props theme)}])])]]))
[rn/view {:style (style/settings-items blur? theme)}
(map-indexed
(fn [index item]
^{:key (str label (:title item))}
[:<>
[settings-item/view item]
(when-not (= last-index index)
[rn/view {:style (style/settings-separator blur? theme)}])])
settings-items)]]))
@@ -11,7 +11,7 @@
:padding-bottom 8})
(defn settings-items
[{:keys [blur?]} theme]
[blur? theme]
{:border-radius 16
:background-color (if blur?
colors/white-opa-5
@@ -22,7 +22,7 @@
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(defn label
[{:keys [blur?]} theme]
[blur? theme]
{:margin-bottom 12
:color (if blur?
colors/white-opa-40
@@ -32,7 +32,7 @@
{:margin-top 12})
(defn settings-separator
[{:keys [blur?]} theme]
[blur? theme]
{:height 1
:background-color (if blur?
colors/white-opa-5
@@ -1,10 +1,13 @@
(ns quo.components.settings.category.view
(:require
[quo.components.settings.category.data-item.view :as data-item]
[quo.components.settings.category.reorder.view :as reorder]
[quo.components.settings.category.settings.view :as settings]))
(defn category
[{:keys [list-type] :as props}]
(if (= list-type :settings)
[settings/settings-category props]
[reorder/reorder-category props]))
(condp = list-type
:settings [settings/settings-category props]
:data-item [data-item/view props]
:reorder [reorder/reorder-category props]
nil))
@@ -116,7 +116,8 @@
[rn/view {:style (style/left-container (:image props))}
[text/text
{:weight :medium
:style {:color (when blur? colors/white)}} title]
:style {:color (when blur? colors/white)}}
title]
[description-component props]
[tag-component props]]]
[rn/view {:style (style/sub-container (:alignment action-props))}
@@ -39,6 +39,12 @@
(def avatar-container-rounded
(assoc avatar-container-common :border-radius 16))
(def big-avatar-container-rounded
(assoc avatar-container-common
:width 84
:height 84
:border-radius 42))
(def community-logo-image
{:width 64
:height 64
+4 -3
View File
@@ -13,8 +13,9 @@
:as props}]
[rn/view {:style style/avatar-overlay}
[rn/view
{:style (if (= avatar-type :wallet-account)
style/avatar-container-rounded
{:style (case avatar-type
:wallet-account style/avatar-container-rounded
:saved-address style/big-avatar-container-rounded
style/avatar-container-circular)}
(case avatar-type
:profile
@@ -37,7 +38,7 @@
[channel-avatar/view (assoc props :locked? nil :size :size-64)]
:saved-address
[wallet-avatar/wallet-user-avatar (assoc props :size :size-64)]
[wallet-avatar/wallet-user-avatar (assoc props :size :size-80)]
nil)]])
@@ -28,5 +28,10 @@
:height 24
:border-radius 12})
(def dapp
{:width 24
:height 24
:border-radius 12})
(def token-image
{:border-radius 12})
@@ -23,6 +23,10 @@
[rn/image
{:source image-source
:style style/network}]
:dapp
[rn/image
{:source image-source
:style style/dapp}]
:saved-address
[wallet-user-avatar/wallet-user-avatar
{:full-name label
@@ -50,7 +54,7 @@
- :label - string - tag label
- :customization-color - color - It will be passed down to components that
should vary based on a custom color.
- :type - :token / :user / :collectible / :saved-address / :network / :account
- :type - :token / :user / :collectible / :saved-address / :network / :account / :dapp
- :emoji - string - emoji used for displaying account avatar
- :image-source - resource - image to display on :network, :collectible and :user
- :theme - :light / :dark"
+8 -8
View File
@@ -7,14 +7,14 @@
[{:keys [blur? customization-color theme selected? container-style]}]
(merge {:border-radius 16
:border-width 1
:border-color (if selected?
(if blur?
colors/white
(colors/resolve-color customization-color theme))
(if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme)))
:padding-bottom 8}
:padding-bottom 8
:border-color (cond
(and selected? blur?) colors/white
selected? (colors/resolve-color customization-color theme)
blur? colors/white-opa-5
:else (colors/theme-colors colors/neutral-10
colors/neutral-80
theme))}
container-style))
(def header-container
+27 -23
View File
@@ -47,12 +47,13 @@
:accessibility-label :title}
[text/text {:weight :semi-bold}
(if (= type :default-keypair) (keypair-string full-name) full-name)]
(if (= action :selector)
[selectors/view
{:type :radio
:checked? selected?
:blur? blur?
:customization-color customization-color}]
(case action
:none nil
:selector [selectors/view
{:type :radio
:checked? selected?
:blur? blur?
:customization-color customization-color}]
[rn/pressable {:on-press on-options-press}
[icon/icon :i/options
{:color (if blur?
@@ -94,20 +95,23 @@
(defn view
[{:keys [accounts action container-style selected? on-press] :as props}]
[rn/pressable
{:style (style/container (merge props
{:selected? selected?
:container-style container-style}))
:on-press #(when (= action :selector) (on-press))}
[rn/view {:style style/header-container}
[avatar props]
[rn/view
{:style {:margin-left 8
:flex 1}}
[title-view (assoc props :selected? selected?)]
[details-view props]]]
[rn/flat-list
{:data accounts
:render-fn acc-list-card
:separator [rn/view {:style {:height 8}}]
:style {:padding-horizontal 8}}]])
(let [theme (quo.theme/use-theme)]
[rn/pressable
{:style (style/container (assoc props
:selected? selected?
:container-style container-style
:theme theme))
:on-press #(when (= action :selector) (on-press))
:pointer-events :box-only}
[rn/view {:style style/header-container}
[avatar props]
[rn/view
{:style {:margin-left 8
:flex 1}}
[title-view (assoc props :selected? selected?)]
[details-view props]]]
[rn/flat-list
{:data accounts
:render-fn acc-list-card
:separator [rn/view {:style {:height 8}}]
:style {:padding-horizontal 8}}]]))
@@ -11,7 +11,7 @@
[utils.i18n :as i18n]))
(defn title-view
[{:keys [keypairs blur? on-import-press]}]
[{:keys [keypairs blur? on-import-press show-import-all?]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :title
@@ -29,12 +29,13 @@
:style {:color colors/warning-60}}
(i18n/label :t/amount-missing-keypairs
{:amount (str (count keypairs))})]
[button/button
{:type :outline
:background :blur
:size 24
:on-press on-import-press}
(i18n/label :t/import)]]
(when show-import-all?
[button/button
{:type :outline
:background :blur
:size 24
:on-press on-import-press}
(i18n/label :t/import)])]
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}
@@ -81,8 +81,9 @@
(js->clj :keywordize-keys true)
(on-selection-change))))]
(fn [{:keys [token customization-color show-keyboard? crypto? currency value error? selection
handle-on-swap]
:or {show-keyboard? true}}]
handle-on-swap allow-selection?]
:or {show-keyboard? true
allow-selection? true}}]
(let [theme (quo.theme/use-theme)
window-width (:width (rn/get-window))]
[rn/pressable
@@ -107,7 +108,8 @@
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?
:on-selection-change handle-selection-change
:selection (clj->js selection)}
:selection (clj->js selection)
:editable allow-selection?}
controlled-input? (assoc :value value)
(not controlled-input?) (assoc :default-value value-internal))]
[token-name-text theme (if crypto? token currency)]]]
+1 -1
View File
@@ -151,7 +151,7 @@
(def black-opa-0 (alpha black 0))
(def black-opa-30 (alpha black 0.3))
(def black-opa-60 (alpha black 0.6))
(def onboarding-header-black "#000716")
(def onboarding-header-black neutral-100)
(def border-avatar-light
"Simulates a blurred, transparent border for avatars in light mode"
"#475060")
+5 -1
View File
@@ -33,6 +33,9 @@
[:fn {:error/message "schema.common/exception should be of type ExceptionInfo"}
(fn [v] (instance? ExceptionInfo v))])
(def ^:private ?hiccup
vector?)
(defn register-schemas
[]
(registry/register ::theme ?theme)
@@ -40,4 +43,5 @@
(registry/register ::public-key ?public-key)
(registry/register ::image-source ?image-source)
(registry/register ::rpc-call ?rpc-call)
(registry/register ::exception ?exception))
(registry/register ::exception ?exception)
(registry/register ::hiccup ?hiccup))
+4 -3
View File
@@ -11,9 +11,10 @@
(defn get-label-by-type
[biometric-type]
(condp = biometric-type
constants/biometrics-type-android (i18n/label :t/biometric-fingerprint)
constants/biometrics-type-face-id (i18n/label :t/biometric-faceid)
(i18n/label :t/biometric-touchid)))
constants/biometrics-type-android (i18n/label :t/biometric-fingerprint)
constants/biometrics-type-face-id (i18n/label :t/biometric-faceid)
constants/biometrics-type-touch-id (i18n/label :t/biometric-touchid)
(i18n/label :t/biometric)))
(defn get-icon-by-type
[biometric-type]
+3 -7
View File
@@ -1,7 +1,6 @@
(ns status-im.common.bottom-sheet.style
(:require
[quo.foundations.colors :as colors]
[react-native.platform :as platform]))
[quo.foundations.colors :as colors]))
(def ^:private sheet-border-radius 20)
@@ -22,11 +21,8 @@
:left 0
:right 0})
(defn shell-bg
[blur-background]
{:background-color (if blur-background
blur-background
(if platform/ios? colors/white-opa-5 colors/neutral-100-opa-90))
(def shell-bg
{:background-color colors/bottom-sheet-background-blur
:flex 1})
(def shell-bg-container
+2 -2
View File
@@ -63,7 +63,7 @@
(defn view
[{:keys [hide? insets]}
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
gradient-cover? customization-color hide-handle? blur-radius blur-background]
gradient-cover? customization-color hide-handle? blur-radius]
:or {border-radius 12}}]
(let [theme (quo.theme/use-theme)
{window-height :height} (rn/get-window)
@@ -134,7 +134,7 @@
(when shell?
[rn/view {:style style/shell-bg-container}
[quo/blur
{:style (style/shell-bg blur-background)
{:style style/shell-bg
:blur-radius (or blur-radius 20)
:blur-amount 32
:blur-type :transparent
@@ -1,6 +1,5 @@
(ns status-im.common.enter-seed-phrase.style
(:require
[react-native.safe-area :as safe-area]))
(:require [react-native.platform :as platform]))
(def full-layout {:flex 1})
@@ -11,6 +10,13 @@
:left 0
:right 0})
(defn recovery-phrase-container
[{:keys [banner-offset insets keyboard-shown?]}]
{:flex 1
:padding-bottom (if keyboard-shown?
(when platform/ios? banner-offset)
(:bottom insets))})
(def form-container
{:flex 1
:padding-horizontal 20
@@ -29,9 +35,7 @@
:margin-top 12
:margin-horizontal -20})
(defn continue-button
[keyboard-shown?]
{:margin-top :auto
:margin-bottom (when-not keyboard-shown? (safe-area/get-bottom))})
(def continue-button
{:margin-top :auto})
(def keyboard-container {:margin-top :auto})
@@ -96,7 +96,7 @@
(take 7)))
(defn recovery-phrase-screen
[{:keys [keypair title recovering-keypair? render-controls]}]
[{:keys [banner-offset initial-insets keypair title recovering-keypair? render-controls]}]
(reagent/with-let [keyboard-shown? (reagent/atom false)
keyboard-show-listener (.addListener rn/keyboard
"keyboardDidShow"
@@ -114,7 +114,8 @@
seed-phrase (reagent/atom "")
on-change-seed-phrase (fn [new-phrase]
(when @invalid-seed-phrase?
(reset! invalid-seed-phrase? false)
(reset! invalid-seed-phrase? false))
(when @incorrect-seed-phrase?
(reset! incorrect-seed-phrase? false))
(reset! seed-phrase new-phrase))
on-submit (fn []
@@ -161,7 +162,10 @@
button-disabled? (or error-state?
(not (constants/seed-phrase-valid-length word-count))
(not all-words-valid?))]
[:<>
[rn/view
{:style (style/recovery-phrase-container {:insets initial-insets
:banner-offset banner-offset
:keyboard-shown? @keyboard-shown?})}
[recovery-phrase-form
{:title title
:keypair keypair
@@ -172,18 +176,18 @@
(if (fn? render-controls)
(render-controls {:submit-disabled? button-disabled?
:keyboard-shown? @keyboard-shown?
:container-style (style/continue-button @keyboard-shown?)
:container-style style/continue-button
:prepare-seed-phrase secure-clean-seed-phrase
:focus-input focus-input
:seed-phrase (security/mask-data @seed-phrase)
:set-incorrect-seed-phrase set-incorrect-seed-phrase})
[quo/button
{:container-style (style/continue-button @keyboard-shown?)
{:container-style style/continue-button
:type :primary
:disabled? button-disabled?
:on-press on-submit}
(i18n/label :t/continue)])]
(when @keyboard-shown?
(when (or @keyboard-shown? error-state?)
[rn/view {:style style/keyboard-container}
[quo/predictive-keyboard
{:type suggestions-state
@@ -197,7 +201,8 @@
(defn screen
[{:keys [initial-insets title keypair navigation-icon recovering-keypair? render-controls]}]
(let [{navigation-bar-top :top} initial-insets]
(let [{navigation-bar-top :top} initial-insets
banner-offset (rf/sub [:alert-banners/top-margin])]
[rn/view {:style style/full-layout}
[rn/keyboard-avoiding-view {:style style/page-container}
[quo/page-nav
@@ -210,6 +215,8 @@
{:title title
:keypair keypair
:render-controls render-controls
:banner-offset banner-offset
:initial-insets initial-insets
:recovering-keypair? recovering-keypair?}]]]))
(defn view
@@ -58,7 +58,7 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
gradient-cover? keyboard-should-persist-taps]
content-container-style gradient-cover? keyboard-should-persist-taps]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@@ -110,7 +110,9 @@
:always-bounce-vertical @keyboard-did-show?
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view {:on-layout set-content-container-height}]
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view
+6 -17
View File
@@ -365,20 +365,10 @@
:sub-label nil
:chevron? false}))
(defn add-members-entry
[chat-id]
(defn add-manage-members-entry
[chat-id admin?]
(entry {:icon :i/add-user
:label (i18n/label :t/add-members)
:on-press #(rf/dispatch [:open-modal :group-add-manage-members chat-id])
:danger? false
:accessibility-label :add-members
:sub-label nil
:chevron? false}))
(defn manage-members-entry
[chat-id]
(entry {:icon :i/add-user
:label (i18n/label :t/manage-members)
:label (i18n/label (if admin? :t/manage-members :t/add-members))
:on-press #(rf/dispatch [:open-modal :group-add-manage-members chat-id])
:danger? false
:accessibility-label :manage-members
@@ -433,8 +423,7 @@
admin? (get admins current-pub-key)]
[(group-details-entry chat-id)
(when inside-chat?
(when admin?
(manage-members-entry chat-id)))
(add-manage-members-entry chat-id admin?))
(when (and admin? inside-chat?)
(when config/show-not-implemented-features?
(edit-group-entry)))
@@ -459,7 +448,7 @@
(destructive-actions item inside-chat?)])])
(defn contact-actions
[{:keys [public-key] :as contact} {:keys [chat-id admin?] :as extra-data}]
[{:keys [public-key added?] :as contact} {:keys [chat-id admin?] :as extra-data}]
(let [current-pub-key (rf/sub [:multiaccount/public-key])]
[quo/action-drawer
[[(view-profile-entry public-key)
@@ -470,7 +459,7 @@
[(when-not (= current-pub-key public-key)
(when config/show-not-implemented-features?
(mark-untrustworthy-entry)))
(when-not (= current-pub-key public-key) (remove-from-contacts-entry contact))
(when added? (remove-from-contacts-entry contact))
(when-not (= current-pub-key public-key) (block-user-entry contact))]
(when (and admin? chat-id)
[(if (= current-pub-key public-key)
@@ -2,12 +2,13 @@
(:require [quo.foundations.colors :as colors]))
(def container
{:flex 1
:padding 10
:margin-vertical 10.5
:border-width 1
:border-color colors/neutral-10
:border-radius 16})
{:flex 1
:padding 10
:margin-top 10.5
:margin-bottom 0
:border-width 1
:border-color colors/neutral-10
:border-radius 16})
(def content
{:padding-bottom 20})
@@ -4,7 +4,7 @@
[status-im.common.raw-data-block.style :as style]))
(defn view
[{:keys [data]}]
[data]
[rn/scroll-view
{:style style/container
:content-container-style style/content}
+4 -2
View File
@@ -195,7 +195,7 @@
true)
(defn view
[{:keys [title subtitle validate-fn on-success-scan error-message share-button?]}]
[{:keys [title subtitle validate-fn on-success-scan error-message share-button? import-keypair?]}]
(let [insets (safe-area/get-insets)
qr-code-succeed? (reagent/atom false)
qr-view-finder (reagent/atom {})
@@ -233,7 +233,9 @@
:set-qr-code-succeeded (fn [value]
(when on-success-scan
(on-success-scan value))
(rf/dispatch [:navigate-back]))
(if import-keypair?
(set-rescan-timeout)
(rf/dispatch [:navigate-back])))
:set-rescan-timeout set-rescan-timeout}])
[rn/view {:style (style/root-container (:top insets))}
[header
@@ -33,6 +33,7 @@
:size 24}]]
[password-input/view
{:on-press-biometrics on-press-biometrics
:blur? true
:processing processing
:error error
:default-password password
@@ -20,7 +20,7 @@
(rf/reg-event-fx :standard-auth/authorize authorize)
(defn authorize-with-biometric
[_ [{:keys [on-auth-success on-auth-fail] :as args}]]
[_ [{:keys [on-auth-success on-auth-fail on-close] :as args}]]
(let [args-with-biometric-btn
(assoc args
:on-press-biometric
@@ -31,7 +31,10 @@
{:prompt-message (i18n/label :t/biometric-auth-confirm-message)
:on-cancel #(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
:on-success #(rf/dispatch [:standard-auth/on-biometric-success on-auth-success])
:on-success (fn []
(when (fn? on-close)
(on-close))
(rf/dispatch [:standard-auth/on-biometric-success on-auth-success]))
:on-fail (fn [err]
(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
+5 -3
View File
@@ -14,10 +14,12 @@
(> (-> s str string/trim count) constants/key-pair-name-max-length))
(defn validation-keypair-name
[s]
[s existing-keypair-names]
(cond
(string/blank? s) nil
(validators/has-emojis? s) (i18n/label :t/key-name-error-emoji)
(validators/has-special-characters? s) (i18n/label :t/key-name-error-special-char)
(keypair-too-short? s) (i18n/label :t/your-key-pair-name-is-too-short)
(keypair-too-long? s) (i18n/label :t/your-key-pair-name-is-too-long)))
(keypair-too-short? s) (i18n/label :t/key-name-error-too-short
{:count constants/key-pair-name-min-length})
(keypair-too-long? s) (i18n/label :t/your-key-pair-name-is-too-long)
(contains? existing-keypair-names s) (i18n/label :t/key-name-error-taken)))
@@ -2,6 +2,7 @@
(:require
[cljs.test :refer-macros [deftest are]]
[status-im.common.validation.keypair :as keypair-validator]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
(deftest keypair-name-too-short-test
@@ -18,10 +19,12 @@
(deftest validation-keypair-name-test
(are [arg expected]
(= (keypair-validator/validation-keypair-name arg) expected)
(= (keypair-validator/validation-keypair-name arg #{"Collection"}) expected)
nil nil
"" nil
"name !" (i18n/label :t/key-name-error-special-char)
"Hello 😊" (i18n/label :t/key-name-error-emoji)
"abc" (i18n/label :t/your-key-pair-name-is-too-short)
"abc" (i18n/label :t/key-name-error-too-short
{:count constants/key-pair-name-min-length})
"Collection" (i18n/label :t/key-name-error-taken)
(apply str (repeat 25 "a")) (i18n/label :t/your-key-pair-name-is-too-long)))
+6
View File
@@ -268,12 +268,14 @@
(def ^:const wallet-connect-personal-sign-method "personal_sign")
(def ^:const wallet-connect-eth-sign-method "eth_sign")
(def ^:const wallet-connect-eth-send-transaction-method "eth_sendTransaction")
(def ^:const wallet-connect-eth-sign-transaction-method "eth_signTransaction")
(def ^:const wallet-connect-eth-sign-typed-method "eth_signTypedData")
(def ^:const wallet-connect-eth-sign-typed-v4-method "eth_signTypedData_v4")
(def ^:const wallet-connect-supported-methods
#{wallet-connect-personal-sign-method
wallet-connect-eth-sign-method
wallet-connect-eth-send-transaction-method
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"})
@@ -492,6 +494,10 @@
(def ^:const optimism-abbreviated-name "Oeth.")
(def ^:const arbitrum-abbreviated-name "Arb1.")
(def ^:const mainnet-full-name "Mainnet")
(def ^:const optimism-full-name "Optimism")
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const mainnet-network-name :mainnet)
(def ^:const ethereum-network-name :ethereum)
(def ^:const optimism-network-name :optimism)
@@ -27,29 +27,37 @@
(rf/dispatch [:deselect-member public-key true]))))
(defn add-member-contact-item-render
[{:keys [public-key] :as item} _ _ {:keys [group]}]
(let [current-pk (rf/sub [:multiaccount/public-key])
{:keys [contacts]} group
[{:keys [public-key] :as item} _ _ {:keys [group admin? current-pk]}]
(let [{:keys [contacts]} group
member? (contains? contacts public-key)
checked? (reagent/atom member?)]
(fn []
(let [on-toggle #(group-chat-member-toggle member? (swap! checked? not) public-key)]
(if (or (= current-pk public-key) (and (not admin?) member?))
(fn []
[contact-list-item/contact-list-item
(when (not= current-pk public-key)
{:disabled? true
:accessory {:disabled? true
:type :checkbox
:checked? @checked?}}
item])
(fn []
(let [on-toggle #(group-chat-member-toggle member? (swap! checked? not) public-key)]
[contact-list-item/contact-list-item
{:on-press on-toggle
:allow-multiple-presses? true
:accessory {:type :checkbox
:checked? @checked?
:on-check on-toggle}})
item]))))
:on-check on-toggle}}
item])))))
(defn add-manage-members
[{:keys [scroll-enabled? on-scroll]}]
(let [selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
chat-id (rf/sub [:get-screen-params :group-add-manage-members])
group (rf/sub [:chats/chat-by-id chat-id])
theme (quo.theme/use-theme)]
(let [theme (quo.theme/use-theme)
selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
chat-id (rf/sub [:get-screen-params :group-add-manage-members])
{:keys [admins] :as group} (rf/sub [:chats/chat-by-id chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view {:flex 1 :margin-top 20}
[rn/touchable-opacity
{:on-press #(rf/dispatch [:navigate-back])
@@ -60,7 +68,7 @@
{:size :heading-1
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label :t/manage-members)]
(i18n/label (if admin? :t/manage-members :t/add-members))]
[gesture/section-list
{:key-fn :title
:scroll-enabled @scroll-enabled?
@@ -70,7 +78,9 @@
:render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn contact-list/contacts-section-footer
:content-container-style {:padding-bottom 20}
:render-data {:group group}
:render-data {:group group
:admin? admin?
:current-pk current-pk}
:render-fn add-member-contact-item-render}]
[rn/view {:style (style/bottom-container 30 theme)}
[quo/button
@@ -159,17 +169,16 @@
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted
constants/mute-till-unmuted)])}
(when admin?
{:accessibility-label :manage-members
:customization-color color
:icon :i/add-user
:label (i18n/label :t/manage-members)
:counter-value (count contacts)
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members
chat-id]))})]}]
{:accessibility-label :manage-members
:customization-color color
:icon :i/add-user
:label (i18n/label (if admin? :t/manage-members :t/add-members))
:counter-value (count contacts)
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members
chat-id]))}]}]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
@@ -16,8 +16,13 @@
contact-id])
{:keys [contact-request-state community-id]} (rf/sub [:chats/current-chat-chat-view])
chat-type (rf/sub [:chats/chat-type])
joined (rf/sub [:communities/community-joined
community-id])
community-chat? (= chat-type :community-chat)
joined (when community-chat?
(rf/sub [:communities/community-joined
community-id]))
pending? (when community-chat?
(rf/sub [:communities/my-pending-request-to-join
community-id]))
contact-request-send? (or (not contact-request-state)
(= contact-request-state
constants/contact-request-state-none))
@@ -28,19 +33,28 @@
[rn/view {:style style/container}
[quo/permission-context
{:blur? true
:on-press (condp = chat-type
:community-chat #(rf/dispatch [:open-modal :community-account-selection-sheet
{:community-id community-id}])
:on-press (cond
(and community-chat? (not pending?) (not joined))
#(rf/dispatch [:open-modal :community-account-selection-sheet
{:community-id community-id}])
(not community-chat?)
#(rf/dispatch [:chat.ui/show-profile contact-id]))
:type :action
:action-icon (cond
(= chat-type :community-chat) :i/communities
contact-request-pending? :i/pending-state
:else :i/add-user)
community-chat? :i/communities
contact-request-pending? :i/pending-state
:else :i/add-user)
:action-label (cond
(= chat-type :community-chat)
(if joined
community-chat?
(cond
pending?
(i18n/label :t/request-to-join-community-pending)
joined
(i18n/label :t/no-permissions-to-post)
:else
(i18n/label :t/join-community-to-post))
(= chat-type :group-chat)
@@ -65,7 +65,7 @@
:as chat} (rf/sub [:chats/chat-by-id chat-id])
pins-count (rf/sub [:chats/pin-messages-count chat-id])
items (rf/sub [:communities/sorted-community-members-section-list
community-id])
community-id chat-id])
theme (quo.theme/use-theme)]
(rn/use-mount (fn []
(rf/dispatch [:pin-message/load-pin-messages chat-id])))
+9 -17
View File
@@ -137,7 +137,7 @@
(rf/reg-event-fx :community/fetch
(fn [_]
{:json-rpc/call [{:method "wakuext_communities"
{:json-rpc/call [{:method "wakuext_serializedCommunities"
:params []
:on-success #(rf/dispatch [:community/fetch-success %])
:on-error #(log/error "failed to fetch communities" %)}
@@ -230,7 +230,7 @@
(when community
{:db (update db :communities/fetching-communities dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [:communities/update-last-opened-at community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data (link-preview.events/community-link community-id)
community]]]}))
@@ -251,7 +251,7 @@
:error err}))
(defn fetch-community
[{:keys [db]} [{:keys [community-id update-last-opened-at?]}]]
[{:keys [db]} [{:keys [community-id]}]]
(when (and community-id
(not (get-in db [:communities community-id]))
(not (get-in db [:communities/fetching-communities community-id])))
@@ -262,11 +262,8 @@
:WaitForResponse true}]
:on-success (fn [community]
(if community
(do (when update-last-opened-at?
(rf/dispatch [:communities/update-last-opened-at
community-id]))
(rf/dispatch [:chat.ui/community-fetched community-id
community]))
(rf/dispatch [:chat.ui/community-fetched community-id
community])
(failed-to-fetch-community
community-id
"community wasn't found at the store node")))
@@ -280,8 +277,7 @@
[:schema
[:vector
[:map {:closed true}
[:community-id {:optional true} :string]
[:update-last-opened-at? {:optional true} [:maybe :boolean]]]]]]]
[:community-id {:optional true} :string]]]]]]
[:maybe
[:map
[:db map?]
@@ -340,10 +336,9 @@
(rf/merge
cofx
{:fx [[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch [:communities/update-last-opened-at community-id]]
[:dispatch
[:communities/fetch-community
{:community-id community-id
:update-last-opened-at? true}]]
[:communities/fetch-community {:community-id community-id}]]
[:dispatch [:navigate-to :community-overview community-id]]
(when (get-in db [:communities community-id :joined])
[:dispatch
@@ -358,10 +353,7 @@
(let [community-id (or community-id (get-in db [:chats chat-id :community-id]))]
(merge
{:fx [(when community-id
[:dispatch
[:communities/fetch-community
{:community-id community-id
:update-last-opened-at? true}]])
[:dispatch [:communities/fetch-community {:community-id community-id}]])
(if pop-to-root?
[:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]]
[:dispatch
@@ -49,7 +49,7 @@
(testing "dispatch fxs"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [:communities/update-last-opened-at community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
@@ -60,7 +60,7 @@
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [:communities/update-last-opened-at community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
@@ -71,7 +71,7 @@
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [:communities/update-last-opened-at community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
@@ -4,7 +4,7 @@
[react-native.platform :as platform]))
(def background-container
{:background-color colors/neutral-95
{:background-color colors/neutral-100
:flex-direction :row
:position :absolute
:overflow :hidden
@@ -29,8 +29,8 @@
[rn/image
{:resize-mode :stretch
:resize-method :scale
:style {:margin-top 32
:width content-width}
:style {:top 138
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
(defonce progress (atom nil))
@@ -1,4 +1,4 @@
(ns status-im.contexts.onboarding.new-to-status.style
(ns status-im.contexts.onboarding.create-or-sync-profile.style
(:require
[quo.foundations.colors :as colors]))
@@ -24,15 +24,4 @@
(def subtitle-container
{:margin-top 24})
(def doc-main-content
{:color colors/white
:margin-bottom 4})
(def doc-subtitle
{:margin-top 20
:margin-bottom 4})
(def doc-content
{:color colors/white-opa-70})
(def space-between-suboptions {:height 12})
@@ -0,0 +1,141 @@
(ns status-im.contexts.onboarding.create-or-sync-profile.view
(:require
[quo.core :as quo]
re-frame.db
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.create-or-sync-profile.style :as style]
[status-im.contexts.onboarding.getting-started-doc.view :as getting-started-doc]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- navigate-to-create-profile
[]
(debounce/throttle-and-dispatch
[:onboarding/navigate-to-create-profile]
1000))
(defn- navigate-to-sign-in-by-syncing
[]
(debounce/throttle-and-dispatch
[:onboarding/navigate-to-sign-in-by-syncing]
1000))
(defn- navigate-to-sign-in-by-seed-phrase
[create-profile?]
(rf/dispatch [:onboarding/navigate-to-sign-in-by-seed-phrase
(if create-profile?
:screen/onboarding.new-to-status
:screen/onboarding.sync-or-recover-profile)]))
(defn- option-card-max-height
[window-height]
(- window-height
(* 2 56) ;; two other list items
(* 2 16) ;; spacing between items
220) ;; extra spacing (top bar)
)
(defn- create-profile-option-card
[window-height]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/generate-keys)
:subtitle (i18n/label :t/generate-keys-subtitle)
:button-label (i18n/label :t/lets-go)
:accessibility-label :generate-key-option-card
:image (resources/get-image :generate-keys)
:max-height (option-card-max-height window-height)
:on-press navigate-to-create-profile}])
(defn- sync-profile-option-card
[window-height]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/sign-in-by-syncing)
:subtitle (i18n/label :t/if-you-have-status-on-another-device)
:button-label (i18n/label :t/scan-sync-code)
:accessibility-label :scan-sync-code-option-card
:image (resources/get-image :generate-keys)
:max-height (option-card-max-height window-height)
:on-press navigate-to-sign-in-by-syncing}])
(defn sign-in-options
[sign-in-type]
(let [window-height (rf/sub [:dimensions/window-height])
create-profile? (= sign-in-type :create-profile)
nav-to-seed-phrase-with-cur-screen (rn/use-callback
#(navigate-to-sign-in-by-seed-phrase
create-profile?)
[create-profile?])
main-option-card (if create-profile?
create-profile-option-card
sync-profile-option-card)]
[rn/view {:style style/options-container}
[quo/text
{:style style/title
:size :heading-1
:weight :semi-bold}
(i18n/label (if create-profile? :t/create-profile :t/sync-or-recover-profile))]
[main-option-card window-height]
[rn/view {:style style/subtitle-container}
[quo/text
{:style style/subtitle
:size :paragraph-2
:weight :medium}
(i18n/label (if create-profile? :t/experienced-web3 :t/dont-have-statatus-on-another-device))]]
[rn/view
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-recovery-phrase)
:subtitle (i18n/label :t/use-recovery-phrase-subtitle)
:accessibility-label :use-recovery-phrase-option-card
:image (resources/get-image :ethereum-address)
:on-press nav-to-seed-phrase-with-cur-screen}]
[rn/view {:style style/space-between-suboptions}]
(when config/show-not-implemented-features?
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle)
:accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard)
:on-press status-im.common.not-implemented/alert}])]]))
(defn- navigate-back
[]
(rf/dispatch [:onboarding/overlay-dismiss])
(rf/dispatch [:navigate-back]))
(defn- navigate-to-quo-preview
[]
(rf/dispatch [:navigate-to :quo-preview]))
(defn- internal-view
[sign-in-type]
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
{:margin-top top
:type :no-title
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back
:right-side [{:icon-name :i/info
:on-press getting-started-doc/show-as-bottom-sheet}
(when config/quo-preview-enabled?
{:icon-name :i/reveal-whitelist
:on-press navigate-to-quo-preview})]}]
[sign-in-options sign-in-type]]))
(defn create-profile
[]
[internal-view :create-profile])
(defn sync-or-recover-profile
[]
[internal-view :sync-or-recover-profile])
@@ -2,7 +2,6 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.contexts.onboarding.enable-notifications.style :as style]
@@ -36,7 +35,7 @@
{:permissions [:post-notifications]
:on-allowed #(log/info "push notification permissions were allowed")
:on-denied #(log/error "user denied push notification permissions")}])
(rf/dispatch [:push-notifications/switch true platform/ios?])
(rf/dispatch [:push-notifications/switch true])
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.enable-notifications]]))
+48 -14
View File
@@ -15,7 +15,10 @@
[{:keys [db]} onboarding-data]
{:db (update db :onboarding/profile merge onboarding-data)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile-password :screen/onboarding.new-to-status]]})
[:screen/onboarding.create-profile-password
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]})
(rf/defn enable-biometrics
{:events [:onboarding/enable-biometrics]}
@@ -25,13 +28,24 @@
{:on-success #(rf/dispatch [:onboarding/biometrics-done])
:on-fail #(rf/dispatch [:onboarding/biometrics-fail %])}]]]})
(rf/defn navigate-to-enable-notifications
{:events [:onboarding/navigate-to-enable-notifications]}
[{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications :screen/onboarding.enable-biometrics]]}))
(rf/reg-event-fx :onboarding/navigate-to-sign-in-by-seed-phrase
(fn [{:keys [db]} [from-screen]]
{:db (assoc db :onboarding/navigated-to-enter-seed-phrase-from-screen from-screen)
:fx [[:dispatch [:navigate-to-within-stack [:screen/onboarding.enter-seed-phrase from-screen]]]]}))
(rf/reg-event-fx :onboarding/navigate-to-enable-notifications-from-syncing
(fn [{:keys [db]}]
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications :screen/onboarding.enable-biometrics]]}))
(rf/reg-event-fx :onboarding/navigate-to-enable-notifications
(fn [{:keys [db]}]
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(rf/defn biometrics-done
{:events [:onboarding/biometrics-done]}
@@ -54,7 +68,10 @@
(:onboarding/profile db)]
(rf/merge cofx
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.generating-keys :screen/onboarding.new-to-status]]
[:screen/onboarding.generating-keys
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
:dispatch [:onboarding/navigate-to-identifiers]}]
:db (-> db
@@ -72,7 +89,7 @@
(merge
{:db (assoc db :profile/profiles-overview multiaccounts)}
(when-not (seq multiaccounts)
{:set-root :screen/onboarding.intro}))))
{:dispatch [:init-root :screen/onboarding.intro]}))))
(rf/defn password-set
{:events [:onboarding/password-set]}
@@ -83,7 +100,10 @@
(assoc-in [:onboarding/profile :auth-method] constants/auth-method-password))
:dispatch (if supported-type
[:navigate-to-within-stack
[:screen/onboarding.enable-biometrics :screen/onboarding.new-to-status]]
[:screen/onboarding.enable-biometrics
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]
[:onboarding/create-account-and-login])}))
(rf/defn navigate-to-enable-biometrics
@@ -118,7 +138,10 @@
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile :screen/onboarding.new-to-status]]}))
[:screen/onboarding.create-profile
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(rf/defn navigate-to-create-profile
{:events [:onboarding/navigate-to-create-profile]}
@@ -128,6 +151,13 @@
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile :screen/onboarding.new-to-status]]})
(rf/reg-event-fx :onboarding/navigate-to-sign-in-by-syncing
(fn [{:keys [db]}]
;; Restart the flow
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.sign-in-intro :screen/onboarding.sync-or-recover-profile]]}))
(rf/reg-event-fx :onboarding/set-auth-method
(fn [{:keys [db]} [auth-method]]
{:db (assoc db :auth-method auth-method)}))
@@ -151,7 +181,8 @@
:on-success (fn []
(rf/dispatch [:onboarding/set-auth-method auth-method])
(when syncing?
(rf/dispatch [:onboarding/navigate-to-enable-notifications])))
(rf/dispatch
[:onboarding/navigate-to-enable-notifications-from-syncing])))
:on-error #(log/error "failed to save biometrics"
{:key-uid key-uid
:error %})}))))
@@ -161,6 +192,9 @@
[{:keys [db]}]
(if (:onboarding/generated-keys? db)
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.identifiers :screen/onboarding.new-to-status]]}
[:screen/onboarding.identifiers
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}
{:dispatch-later [{:ms constants/onboarding-generating-keys-navigation-retry-ms
:dispatch [:onboarding/navigate-to-identifiers]}]}))
@@ -0,0 +1,14 @@
(ns status-im.contexts.onboarding.getting-started-doc.style
(:require
[quo.foundations.colors :as colors]))
(def main-content
{:color colors/white
:margin-bottom 4})
(def subtitle
{:margin-top 20
:margin-bottom 4})
(def content
{:color colors/white-opa-70})
@@ -0,0 +1,50 @@
(ns status-im.contexts.onboarding.getting-started-doc.view
(:require
[quo.core :as quo]
[status-im.contexts.onboarding.getting-started-doc.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn getting-started-doc
[]
[quo/documentation-drawers
{:title (i18n/label :t/getting-started-with-status)
:shell? true}
[:<>
[quo/text
{:size :paragraph-2
:style style/main-content}
(i18n/label :t/getting-started-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/generate-keys)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-on-keycard)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-on-keycard-description)]]])
(defn show-as-bottom-sheet
[]
(rf/dispatch [:show-bottom-sheet
{:content getting-started-doc
:shell? true}]))
@@ -20,6 +20,10 @@
{:text (i18n/label :t/emojihash)
:sub-text (i18n/label :t/emojihash-description)}])
(defn- navigate-to-enable-notifications
[]
(rf/dispatch [:onboarding/navigate-to-enable-notifications]))
(defn f-view
[]
(let [progress (atom nil)
@@ -62,9 +66,7 @@
{:accessibility-label :skip-identifiers
:type :grey
:background :blur
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
:screen/onboarding.new-to-status]])
:on-press navigate-to-enable-notifications
:container-style style/button}
(i18n/label :t/continue)]]]]))
@@ -7,9 +7,10 @@
:justify-content :flex-end})
(def text-container
{:flex 1
:max-width 180
:flex-wrap :wrap})
{:flex 1
:text-align :center
:margin-top 16
:flex-wrap :wrap})
(def plain-text
{:color colors/white-opa-70})
@@ -17,3 +18,10 @@
(def highlighted-text
{:flex 1
:color colors/white})
(def bottom-actions-container
{:position :absolute
:background-color colors/onboarding-header-black
:left 0
:right 0
:padding-bottom 40})
@@ -2,12 +2,10 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.constants :as constants]
[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]
[status-im.contexts.onboarding.terms.view :as terms]
[status-im.contexts.syncing.scan-sync-code.view :as scan-sync-code]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -15,40 +13,37 @@
[]
[rn/view {:style style/page-container}
[background/view false]
[quo/drawer-buttons
{:on-init (fn [reset-top-animation-fn]
(reset! scan-sync-code/dismiss-animations reset-top-animation-fn))
:animations-duration constants/onboarding-modal-animation-duration
:animations-delay constants/onboarding-modal-animation-delay
:top-card {:on-press #(rf/dispatch [:open-modal
:screen/onboarding.sign-in-intro])
:heading (i18n/label :t/sign-in)
:animated-heading (i18n/label :t/sign-in-by-syncing)
:accessibility-label :already-use-status-button}
:bottom-card {:on-press (fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal :screen/onboarding.new-to-status]))
:heading (i18n/label :t/new-to-status)
:accessibility-label :new-to-status-button}}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
(i18n/label :t/you-already-use-status)]
[quo/text {:style style/text-container}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [terms/terms-of-use])
:shell? true}])
:size :paragraph-2
:weight :regular
:style style/highlighted-text}
(i18n/label :t/terms-of-service)]]]
[quo/bottom-actions
{:container-style style/bottom-actions-container
:actions :two-vertical-actions
:description :bottom
:description-text [quo/text
{:style style/text-container
:size :paragraph-2
:weight :regular}
[quo/text {:style style/plain-text}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [terms/terms-of-use])
:shell? true}])
:style style/highlighted-text}
(i18n/label :t/terms-of-service)]]
:button-one-label (i18n/label :t/sync-or-recover-profile)
:button-one-props {:type :dark-grey
:accessibility-label :already-use-status-button
:on-press (fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal
:screen/onboarding.sync-or-recover-profile]))}
:button-two-label (i18n/label :t/create-profile)
:button-two-props {:accessibility-label :new-to-status-button
:on-press
(fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal :screen/onboarding.new-to-status]))}}]
[overlay/view]])
@@ -1,117 +0,0 @@
(ns status-im.contexts.onboarding.new-to-status.view
(:require
[quo.core :as quo]
re-frame.db
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.new-to-status.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn sign-in-options
[]
(let [window (rf/sub [:dimensions/window])]
[rn/view {:style style/options-container}
[quo/text
{:style style/title
:size :heading-1
:weight :semi-bold}
(i18n/label :t/new-to-status)]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/generate-keys)
:subtitle (i18n/label :t/generate-keys-subtitle)
:button-label (i18n/label :t/lets-go)
:image (resources/get-image :generate-keys)
:max-height (- (:height window)
(* 2 56) ;; two other list items
(* 2 16) ;; spacing between items
220) ;; extra spacing (top bar)
:on-press #(debounce/throttle-and-dispatch
[:onboarding/navigate-to-create-profile]
1000)}]
[rn/view {:style style/subtitle-container}
[quo/text
{:style style/subtitle
:size :paragraph-2
:weight :medium}
(i18n/label :t/experienced-web3)]]
[rn/view
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-recovery-phrase)
:subtitle (i18n/label :t/use-recovery-phrase-subtitle)
:image (resources/get-image :ethereum-address)
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.enter-seed-phrase
:screen/onboarding.new-to-status]])}]
[rn/view {:style style/space-between-suboptions}]
(when config/show-not-implemented-features?
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle)
:image (resources/get-image :use-keycard)
:on-press #(js/alert "TODO: to be implemented")}])]]))
(defn getting-started-doc
[]
[quo/documentation-drawers
{:title (i18n/label :t/getting-started-with-status)
:shell? true}
[:<>
[quo/text
{:size :paragraph-2
:style style/doc-main-content}
(i18n/label :t/getting-started-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/generate-keys)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-on-keycard)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-on-keycard-description)]]])
(defn new-to-status
[]
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
{:margin-top top
:type :no-title
:background :blur
:icon-name :i/arrow-left
:on-press #(do
(rf/dispatch [:onboarding/overlay-dismiss])
(rf/dispatch [:navigate-back]))
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content getting-started-doc
:shell? true}])}
(when config/quo-preview-enabled?
{:icon-name :i/reveal-whitelist
:on-press #(rf/dispatch [:navigate-to :quo-preview])})]}]
[sign-in-options]]))
@@ -1,6 +1,7 @@
(ns status-im.contexts.preview.quo.settings.category
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[reagent.core :as reagent]
[status-im.common.resources :as resources]
[status-im.contexts.preview.quo.preview :as preview]))
@@ -17,6 +18,24 @@
:image-props :i/browser
:image-size 32})))
(defn create-data-item-array
[n]
(vec
(for [i (range n)]
{:blur? false
:description :default
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10
:card? false
:label :preview
:status :default
:size :default
:right-content {:type :accounts
:data [{:emoji "🔥" :customization-color :yellow}]}
:title (str "Item title " i)
:subtitle "Item subtitle"})))
(def descriptor
[{:key :blur? :type :boolean}
{:key :list-type
@@ -24,7 +43,11 @@
:options [{:key :settings
:value :settings}
{:key :reorder
:value :reorder}]}])
:value :reorder}
{:key :data-item
:value :data-item}]}])
(def ^:constant n-items 5)
(defn view
[]
@@ -32,7 +55,10 @@
:blur? false
:list-type :settings})]
(fn []
(let [data (create-item-array 5)]
(let [list-type (:list-type @state)
data (if (= list-type :data-item)
(create-data-item-array n-items)
(create-item-array n-items))]
[preview/preview-container
{:state state
:descriptor descriptor
@@ -51,7 +51,9 @@
{:value "Saved address"
:key :saved-address}
{:value "Account"
:key :account}]}])
:key :account}
{:value "Dapp"
:key :dapp}]}])
(defn view
[]
@@ -23,6 +23,8 @@
:options [{:key :usd}
{:key :eur}]}
{:key :error?
:type :boolean}
{:key :allow-selection?
:type :boolean}])
(defn view
@@ -33,7 +35,8 @@
:networks networks
:title title
:customization-color :blue
:show-keyboard? false})
:show-keyboard? false
:allow-selection? true})
value (reagent/atom "")
set-value (fn [v]
(swap! value str v))
+1 -1
View File
@@ -40,7 +40,7 @@
:verifyENSURL config/verify-ens-url
:verifyENSContractAddress config/verify-ens-contract-address
:verifyTransactionChainID config/verify-transaction-chain-id
:wakuV2LightClient false
:wakuV2LightClient true
:previewPrivacy config/blank-preview?
:testNetworksEnabled config/test-networks-enabled?})))
@@ -3,6 +3,7 @@
[quo.foundations.colors :as colors]
[status-im.common.not-implemented :as not-implemented]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.profile.edit.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
@@ -19,7 +20,7 @@
:on-press #(rf/dispatch [:open-modal :edit-name])
:blur? true
:label :text
:label-props full-name
:label-props (utils/truncate-str full-name constants/profile-name-max-length)
:action :arrow
:container-style style/item-container}
{:title (i18n/label :t/bio)
+2 -2
View File
@@ -45,14 +45,14 @@
(assoc :profile/profiles-overview profiles)
(update :profile/login #(select-profile % key-uid)))
db)
:fx [[:set-root :screen/profile.profiles]
:fx [[:dispatch [:init-root :screen/profile.profiles]]
(when key-uid
[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success (fn [auth-method]
(rf/dispatch [:profile.login/check-biometric-success key-uid
auth-method]))}])]})
{:fx [[:set-root :screen/onboarding.intro]]})))
{:fx [[:dispatch [:init-root :screen/onboarding.intro]]]})))
(rf/reg-event-fx
:profile/update-setting-from-backup
@@ -74,7 +74,7 @@
(cond
pairing-completed?
[[:set-root :screen/onboarding.syncing-results]]
[[:dispatch [:init-root :screen/onboarding.syncing-results]]]
(get db :onboarding/new-account?)
[[:dispatch [:onboarding/finalize-setup]]]
@@ -85,7 +85,7 @@
constants/theme-type-dark)
:shell-stack
false]]
[:set-root :shell-stack]
[:dispatch [:init-root :shell-stack]]
[:dispatch [:profile/show-testnet-mode-banner-if-enabled]]]))})))
;; login phase 2: we want to load and show chats faster, so we split login into 2 phases
@@ -179,7 +179,7 @@
{:db (-> db
(assoc-in [:profile/login :password] password)
(assoc-in [:profile/login :processing] true))
:fx [[:set-root :progress]
:fx [[:dispatch [:init-root :progress]]
[:effects.profile/login
[(get-in db [:profile/login :key-uid])
(security/safe-unmask-data password)]]]})))
@@ -1,24 +1,5 @@
(ns status-im.contexts.settings.wallet.data-store)
(defn extract-keypair-name
[db key-uids-set]
(when (= (count key-uids-set) 1)
(let [key-uid (first key-uids-set)
keypairs (get-in db [:wallet :keypairs])]
(->> (filter #(= (:key-uid %) key-uid) keypairs)
first
:name))))
(defn update-keypair
[keypairs key-uid update-fn]
(mapcat (fn [keypair]
(if (= (keypair :key-uid) key-uid)
(if-let [updated (update-fn keypair)]
[updated]
[])
[keypair]))
keypairs))
(defn make-accounts-fully-operable
"Updates accounts to be fully operable based on specified key-uids and an optional operable condition.
@@ -32,10 +13,10 @@
- A new map with accounts updated to be fully operable where the conditions are met."
[{:keys [accounts key-uids-set operable-condition]}]
(reduce-kv
(fn [acc k account]
(if (and (contains? key-uids-set (:key-uid account))
(fn [acc k {:keys [key-uid] :as account}]
(if (and (contains? key-uids-set key-uid)
(or (nil? operable-condition)
(= (keyword (:operable account)) operable-condition)))
(= (:operable account) operable-condition)))
(assoc acc k (assoc account :operable :fully))
(assoc acc k account)))
{}
@@ -44,7 +25,7 @@
(defn- make-keypairs-accounts-fully-operable
[accounts operable-condition]
(map (fn [account]
(if (or (nil? operable-condition) (= (keyword (:operable account)) operable-condition))
(if (or (nil? operable-condition) (= (:operable account) operable-condition))
(assoc account :operable :fully)
account))
accounts))
@@ -53,27 +34,30 @@
"Updates keypairs' accounts to be fully operable based on specified key-uids and an optional operable condition.
Parameters:
- :keypairs (seq): A sequence of keypair maps.
- :keypairs (map): A map of keypair key-uid to keypair details.
- :key-uids-set (set): A set of key-uids that need to be checked and updated.
- :operable-condition (keyword, optional): The condition that the keypair's accounts' operability must meet to be updated.
If nil or not provided, the function will update all keypairs' accounts.
Returns:
- A new sequence with keypairs updated to be fully operable where the conditions are met."
- A new map with keypairs updated to be fully operable where the conditions are met."
[{:keys [keypairs key-uids-set operable-condition]}]
(map (fn [keypair]
(if (contains? key-uids-set (:key-uid keypair))
(-> keypair
(update :accounts #(make-keypairs-accounts-fully-operable % operable-condition))
(assoc :lowest-operability :fully))
keypair))
keypairs))
(reduce-kv (fn [acc k keypair]
(if (contains? key-uids-set k)
(assoc acc
k
(-> keypair
(update :accounts make-keypairs-accounts-fully-operable operable-condition)
(assoc :lowest-operability :fully)))
(assoc acc k keypair)))
{}
keypairs))
(defn map-addresses-to-key-uids
(defn get-keypair-key-uids-set-from-addresses
[db addresses]
(reduce (fn [key-uid-set address]
(if-let [account (get-in db [:wallet :accounts address])]
(conj key-uid-set (:key-uid account))
(if-let [account-key-uid (get-in db [:wallet :accounts address :key-uid])]
(conj key-uid-set account-key-uid)
key-uid-set))
#{}
addresses))
@@ -10,9 +10,7 @@
(rf/reg-event-fx
:wallet/rename-keypair-success
(fn [{:keys [db]} [key-uid name]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [keypair] (assoc keypair :name name))))
{:db (update-in db [:wallet :keypairs key-uid] assoc :name name)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
@@ -49,9 +47,7 @@
(rf/reg-event-fx :wallet/remove-keypair-success
(fn [{:keys [db]} [key-uid]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [_] nil)))
{:db (update-in db [:wallet :keypairs] dissoc key-uid)
:fx [[:dispatch [:hide-bottom-sheet]]
[:dispatch
[:toasts/upsert
@@ -71,8 +67,11 @@
(defn make-keypairs-accounts-fully-operable
[{:keys [db]} [key-uids-to-update]]
(let [key-uids-set (set key-uids-to-update)
keypair-name (data-store/extract-keypair-name db key-uids-set)]
(let [key-uids-set (set key-uids-to-update)
single-keypair-to-update? (= (count key-uids-to-update) 1)
keypair-name (when single-keypair-to-update?
(let [key-uid (first key-uids-set)]
(get-in db [:wallet :keypairs key-uid :name])))]
{:db (->
db
(update-in [:wallet :accounts]
@@ -85,7 +84,7 @@
[:toasts/upsert
{:type :positive
:theme :dark
:text (if (= (count key-uids-to-update) 1)
:text (if single-keypair-to-update?
(i18n/label :t/key-pair-imported-successfully {:name keypair-name})
(i18n/label :t/key-pairs-successfully-imported
{:count (count key-uids-to-update)}))}]]]}))
@@ -93,23 +92,28 @@
(rf/reg-event-fx :wallet/make-keypairs-accounts-fully-operable make-keypairs-accounts-fully-operable)
(defn connection-string-for-import-keypair
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string]}]]
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string on-success]}]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids keypairs-key-uids
:connection-string connection-string
:on-success #(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable %])
:on-fail #(rf/dispatch [:toasts/upsert
{:type :negative
:theme :dark
:text %}])}]]}))
:on-success (fn [key-uids]
(rf/call-continuation on-success)
(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable key-uids]))
:on-fail (fn [error]
(log/error "failed to import missing key pairs with connection string"
{:error error})
(rf/dispatch [:toasts/upsert
{:type :negative
:theme :dark
:text (i18n/label :t/incorrect-qr-code)}]))}]]}))
(rf/reg-event-fx :wallet/connection-string-for-import-keypair connection-string-for-import-keypair)
(defn success-keypair-qr-scan
[_ [connection-string keypairs-key-uids]]
[_ [connection-string keypairs-key-uids on-import-success]]
{:fx [[:dispatch
[:standard-auth/authorize-with-password
{:blur? true
@@ -121,7 +125,8 @@
[:wallet/connection-string-for-import-keypair
{:connection-string connection-string
:keypairs-key-uids keypairs-key-uids
:sha3-pwd password}]))}]]]})
:sha3-pwd password
:on-success on-import-success}]))}]]]})
(rf/reg-event-fx :wallet/success-keypair-qr-scan success-keypair-qr-scan)
@@ -147,7 +152,7 @@
{:fx [[:json-rpc/call
[{:method "accounts_makePrivateKeyKeypairFullyOperable"
:params [(security/safe-unmask-data private-key)
(-> password security/safe-unmask-data native-module/sha3)]
(security/safe-unmask-data password)]
:on-success on-success
:on-error on-error}]]]})
@@ -231,7 +236,7 @@
(defn make-partially-operable-accounts-fully-operable-success
[{:keys [db]} [addresses]]
(let [key-uids-to-update (data-store/map-addresses-to-key-uids db addresses)]
(let [key-uids-to-update (data-store/get-keypair-key-uids-set-from-addresses db addresses)]
{:db (-> db
(update-in [:wallet :accounts]
#(data-store/make-accounts-fully-operable {:accounts %
@@ -1,104 +1,100 @@
(ns status-im.contexts.settings.wallet.events-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[cljs.test :refer-macros [deftest is]]
matcher-combinators.test
[native-module.core :as native-module]
[status-im.contexts.settings.wallet.events :as sut]
[utils.security.core :as security]))
(def mock-key-uid "key-1")
(defn mock-db
[keypairs accounts]
{:wallet {:keypairs keypairs
:accounts accounts}
:profile/profile {:key-uid "test-key-uid"}})
(def test-profile {:key-uid "test-key-uid"})
(def test-keypair-key-uid "key-1")
(deftest rename-keypair-test
(let [new-keypair-name "key pair new"
cofx {:db {}}]
(testing "rename-keypair"
(let [expected {:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [mock-key-uid new-keypair-name]
:on-success [:wallet/rename-keypair-success mock-key-uid
new-keypair-name]
:on-error fn?}]]]}]
(is (match? expected
(sut/rename-keypair cofx
[{:key-uid mock-key-uid
:keypair-name new-keypair-name}])))))))
cofx {:db {}}
expected {:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [test-keypair-key-uid new-keypair-name]
:on-success [:wallet/rename-keypair-success test-keypair-key-uid
new-keypair-name]
:on-error fn?}]]]}]
(is (match? expected
(sut/rename-keypair cofx
[{:key-uid test-keypair-key-uid
:keypair-name new-keypair-name}])))))
(deftest get-keypair-export-connection-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db {:profile/profile test-profile}}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
callback (fn [connect-string] (println "callback" connect-string))]
(testing "get-keypair-export-connection"
(let [expected {:fx [[:effects.syncing/export-keypairs-keystores
callback (fn [connect-string] (println "callback" connect-string))
expected {:fx [[:effects.syncing/export-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypair-key-uid mock-key-uid
:keypair-key-uid test-keypair-key-uid
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/get-keypair-export-connection
cofx
[{:sha3-pwd sha3-pwd :keypair-key-uid mock-key-uid :callback callback}])))))))
(is (match?
expected
(sut/get-keypair-export-connection
cofx
[{:sha3-pwd sha3-pwd :keypair-key-uid test-keypair-key-uid :callback callback}])))))
(deftest remove-keypair-test
(let [cofx {:db {}}]
(testing "remove-keypair"
(let [expected {:fx [[:json-rpc/call
[{:method "accounts_deleteKeypair"
:params [mock-key-uid]
:on-success [:wallet/remove-keypair-success mock-key-uid]
:on-error fn?}]]]}]
(is (match? expected
(sut/remove-keypair cofx [mock-key-uid])))))))
(let [cofx {:db {}}
expected {:fx [[:json-rpc/call
[{:method "accounts_deleteKeypair"
:params [test-keypair-key-uid]
:on-success [:wallet/remove-keypair-success test-keypair-key-uid]
:on-error fn?}]]]}]
(is (match? expected
(sut/remove-keypair cofx [test-keypair-key-uid])))))
(deftest make-keypairs-accounts-fully-operable-test
(let [db (mock-db [{:key-uid mock-key-uid
:lowest-operability :no
:accounts [{:key-uid mock-key-uid :operable "no"}]}]
{"0x1" {:key-uid mock-key-uid :operable "no"}})
key-uids-to-update [mock-key-uid]]
(testing "make-keypairs-accounts-fully-operable"
(let [effects (sut/make-keypairs-accounts-fully-operable {:db db} [key-uids-to-update])
result-db (:db effects)
updated-keypair (some #(when (= (:key-uid %) mock-key-uid) %)
(get-in result-db [:wallet :keypairs]))
updated-account (get-in result-db [:wallet :accounts "0x1"])]
(is (= (keyword (-> updated-keypair :accounts first :operable)) :fully))
(is (= (keyword (:operable updated-account)) :fully))
(is (= (:lowest-operability updated-keypair) :fully))))))
(let [db {:wallet {:keypairs {test-keypair-key-uid {:key-uid
test-keypair-key-uid
:lowest-operability :no
:accounts
[{:key-uid
test-keypair-key-uid
:operable :no}]}}
:accounts {"0x1" {:key-uid test-keypair-key-uid
:operable :no}}}
:profile/profile test-profile}
key-uids-to-update [test-keypair-key-uid]
effects (sut/make-keypairs-accounts-fully-operable {:db db} [key-uids-to-update])
result-db (:db effects)
updated-keypair (get-in result-db [:wallet :keypairs test-keypair-key-uid])
updated-account (get-in result-db [:wallet :accounts "0x1"])]
(is (= (-> updated-keypair :accounts first :operable) :fully))
(is (= (:operable updated-account) :fully))
(is (= (:lowest-operability updated-keypair) :fully))))
(deftest connection-string-for-import-keypair-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db {:profile/profile test-profile}}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
connection-string "test-connection-string"]
(testing "connection-string-for-import-keypair"
(let [expected {:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids [mock-key-uid]
:connection-string connection-string
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/connection-string-for-import-keypair cofx
[{:sha3-pwd sha3-pwd
:keypairs-key-uids [mock-key-uid]
:connection-string
connection-string}])))))))
connection-string "test-connection-string"
expected {:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids [test-keypair-key-uid]
:connection-string connection-string
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/connection-string-for-import-keypair cofx
[{:sha3-pwd sha3-pwd
:keypairs-key-uids [test-keypair-key-uid]
:connection-string
connection-string}])))))
(deftest success-keypair-qr-scan-test
(let [connection-string "valid-connection-string"
keypairs-key-uids ["keypair-uid"]]
(testing "success-keypair-qr-scan"
(let [effects (sut/success-keypair-qr-scan nil [connection-string keypairs-key-uids])
fx (:fx effects)]
(is (some? fx))))))
keypairs-key-uids [test-keypair-key-uid]
effects (sut/success-keypair-qr-scan nil [connection-string keypairs-key-uids])
fx (:fx effects)]
(is (some? fx))))
(deftest wallet-validate-seed-phrase-test
(let [cofx {:db {}}
@@ -41,31 +41,37 @@
[quo/action-drawer
[(when has-paired-device
(if-not missing-keypair?
[{:icon :i/qr-code
[{:blur? true
:icon :i/qr-code
:accessibility-label :show-key-pr-qr
:label (i18n/label :t/show-encrypted-qr-of-key-pairs)
:on-press on-show-qr}]
[{:icon :i/scan
[{:blur? true
:icon :i/scan
:accessibility-label :import-by-scan-qr
:label (i18n/label :t/import-by-scanning-encrypted-qr)
:on-press on-scan-qr}]))
(when (= (:type drawer-props) :keypair)
[(when missing-keypair?
(case (:type keypair)
:seed {:icon :i/seed
:seed {:blur? true
:icon :i/seed
:accessibility-label :import-seed-phrase
:label (i18n/label :t/import-by-entering-recovery-phrase)
:on-press on-import-seed-phrase}
:key {:icon :i/key
:key {:blur? true
:icon :i/key
:accessibility-label :import-private-key
:label (i18n/label :t/import-by-entering-private-key)
:on-press on-import-private-key}
nil))
{:icon :i/edit
{:blur? true
:icon :i/edit
:accessibility-label :rename-key-pair
:label (i18n/label :t/rename-key-pair)
:on-press on-rename-keypair}
{:icon :i/delete
{:blur? true
:icon :i/delete
:accessibility-label :remove-key-pair
:add-divider? true
:danger? true
@@ -11,13 +11,16 @@
[]
(let [keypairs-key-uids (rf/sub [:get-screen-params])
on-success-scan (rn/use-callback (fn [scanned-text]
(rf/dispatch [:wallet/success-keypair-qr-scan scanned-text
keypairs-key-uids])
(rf/dispatch [:wallet/success-keypair-qr-scan
scanned-text
keypairs-key-uids
[:navigate-back]])
[keypairs-key-uids]))]
[scan-qr-code/view
{:title (i18n/label :t/scan-key-pairs-qr-code)
:subtitle (i18n/label :t/find-it-in-setting)
:share-button? false
:import-keypair? true
:validate-fn sync-utils/valid-connection-string?
:error-message (i18n/label :t/invalid-qr)
:error-message (i18n/label :t/invalid-key-pair-qr)
:on-success-scan on-success-scan}]))
@@ -4,7 +4,8 @@
{:margin-bottom 8})
(def bottom-action
{:margin-horizontal -20})
{:margin-horizontal -20
:margin-vertical -12})
(def error-container
{:margin-left 20
@@ -2,6 +2,7 @@
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.validation.keypair :as keypair-validator]
[status-im.constants :as constants]
@@ -14,19 +15,24 @@
(defn view
[]
(let [{:keys [name key-uid]} (rf/sub [:get-screen-params])
(let [insets (safe-area/get-insets)
{existing-keypair-name :name
:keys [key-uid]} (rf/sub [:get-screen-params])
existing-keypair-names (rf/sub [:wallet/keypair-names])
customization-color (rf/sub [:profile/customization-color])
[unsaved-keypair-name set-unsaved-keypair-name] (rn/use-state name)
[unsaved-keypair-name set-unsaved-keypair-name] (rn/use-state existing-keypair-name)
[error-msg set-error-msg] (rn/use-state nil)
[typing? set-typing?] (rn/use-state false)
validate-keypair-name (rn/use-callback
(debounce/debounce
(fn [name]
(fn [input-name]
(set-error-msg
(keypair-validator/validation-keypair-name
name))
input-name
existing-keypair-names))
(set-typing? false))
300))
300)
[existing-keypair-names])
on-change-text (rn/use-callback (fn [text]
(set-typing? true)
(set-unsaved-keypair-name
@@ -40,45 +46,57 @@
:keypair-name
unsaved-keypair-name}])
[unsaved-keypair-name key-uid])]
[floating-button-page/view
{:header [quo/page-nav
{:icon-name :i/close
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save)
:button-one-props {:disabled? (or typing?
(string/blank? unsaved-keypair-name)
(not (string/blank? error-msg)))
:customization-color customization-color
:on-press on-save}
:container-style style/bottom-action}]}
[quo/page-top
{:container-style style/header-container
:title (i18n/label :t/rename-key-pair)
:description :context-tag
:context-tag {:type :icon
:size 24
:context name
:icon :i/seed-phrase}}]
[quo/input
{:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:default-value unsaved-keypair-name
:char-limit constants/key-pair-name-max-length
:max-length constants/key-pair-name-max-length
:auto-focus true
:clearable? (not (string/blank? unsaved-keypair-name))
:on-clear on-clear
:on-change-text on-change-text
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]))
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
:blur? true
:header [quo/page-nav
{:margin-top (:top insets)
:icon-name :i/close
:background :blur
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:blur? true
:button-one-label (i18n/label :t/save)
:button-one-props {:blur? true
:disabled? (or typing?
(= existing-keypair-name
unsaved-keypair-name)
(string/blank?
unsaved-keypair-name)
(not (string/blank?
error-msg)))
:customization-color customization-color
:on-press on-save}
:container-style style/bottom-action}]}
[quo/page-top
{:container-style style/header-container
:title (i18n/label :t/rename-key-pair)
:description :context-tag
:blur? true
:context-tag {:type :icon
:size 24
:context existing-keypair-name
:icon :i/seed-phrase}}]
[quo/input
{:blur? true
:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:default-value unsaved-keypair-name
:char-limit constants/key-pair-name-max-length
:auto-focus true
:clearable? (not (string/blank? unsaved-keypair-name))
:on-clear on-clear
:on-change-text on-change-text
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]]))
@@ -1,11 +1,11 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.settings.wallet.keypairs-and-accounts.actions.view :as actions]
[status-im.contexts.settings.wallet.keypairs-and-accounts.style :as style]
[status-im.feature-flags :as ff]
[utils.address :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -17,13 +17,12 @@
(defn on-options-press
[{:keys [drawer-props keypair]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/view
{:drawer-props drawer-props
:keypair keypair}])
{:content (fn [] [actions/view
{:drawer-props drawer-props
:keypair keypair}])
:blur-background colors/bottom-sheet-background-blur
:theme (:theme drawer-props)
:shell? true}]))
:theme (:theme drawer-props)
:shell? true}]))
(defn options-drawer-props
[{{:keys [name]} :keypair
@@ -70,7 +69,7 @@
{:blur? true
:status-indicator false
:stored :on-device
:action :options
:action (if default-keypair? :none :options)
:accounts accounts
:customization-color customization-color
:container-style style/keypair-container-style
@@ -83,17 +82,16 @@
(defn on-missing-keypair-options-press
[_event keypair-data]
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:blur-background colors/bottom-sheet-background-blur
:content (fn [] [actions/view
{:keypair keypair-data
:drawer-props (options-drawer-props
{:theme :dark
:type :keypair
:stored :missing
:blur? true
:keypair keypair-data})}])}]))
{:theme :dark
:shell? true
:content (fn [] [actions/view
{:keypair keypair-data
:drawer-props (options-drawer-props
{:theme :dark
:type :keypair
:stored :missing
:blur? true
:keypair keypair-data})}])}]))
(defn view
[]
@@ -127,6 +125,7 @@
:header (when (seq missing-keypairs)
[quo/missing-keypairs
{:blur? true
:show-import-all? (ff/enabled? ::ff/settings.import-all-keypairs)
:keypairs missing-keypairs
:on-import-press on-import-press
:container-style style/missing-keypairs-container-style
@@ -1,6 +1,5 @@
(ns status-im.contexts.settings.wallet.network-settings.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as resources]
[quo.theme]
[react-native.core :as rn]
@@ -80,12 +79,11 @@
(defn on-change-testnet
[{:keys [enable? blur? theme]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [testnet/view
{:enable? enable?
:blur? blur?}])
:theme theme
:shell? blur?
:blur-background colors/bottom-sheet-background-blur}]))
{:content (fn [] [testnet/view
{:enable? enable?
:blur? blur?}])
:theme theme
:shell? blur?}]))
(defn view
[]
@@ -27,4 +27,5 @@
{:color colors/white-opa-40})
(def saved-address-item
{:margin-top 4})
{:margin-top 4
:background-color colors/white-opa-5})
@@ -49,6 +49,7 @@
:multiline? true
:on-clear clear-input
:return-key-type :done
:auto-focus true
:clearable? (not empty-input?)
:on-change-text on-change-text
:button (when empty-input?
@@ -83,7 +84,7 @@
[quo/info-message
{:accessibility-label :error-message
:size :default
:icon :i/info
:icon :i/alert
:type :error
:style style/info-message}
error-msg])))
@@ -91,8 +92,7 @@
(defn- existing-saved-address
[{:keys [address]}]
(let [{:keys [name customization-color chain-short-names ens ens?]}
(rf/sub [:wallet/saved-address-by-address
address])]
(rf/sub [:wallet/saved-address-by-address address])]
[rn/view {:style style/existing-saved-address-container}
[quo/text
{:size :paragraph-1
@@ -93,20 +93,19 @@
:subtitle-type :default
:label :none
:blur? true
:icon-right? (not ens?)
:right-icon :i/advanced
:right-icon (when-not ens? :i/advanced)
:card? true
:title (i18n/label :t/address)
:subtitle ens
:custom-subtitle address-text
:on-press open-network-preferences
:on-press (when-not ens? open-network-preferences)
:container-style style/data-item}
ens?
(dissoc :custom-subtitle))
[ens ens? open-network-preferences address-text])]
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
{:footer-container-padding (if edit? (+ (safe-area/get-bottom) 12) 0)
:header [quo/page-nav
{:type :no-title
:background :blur
@@ -133,7 +132,7 @@
:container-style style/avatar}]
[quo/title-input
{:blur? true
:auto-focus true
:auto-focus (not edit?)
:max-length 24
:size :heading-1
:placeholder placeholder
@@ -2,20 +2,24 @@
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[status-im.constants :as constants]
[status-im.contexts.settings.wallet.saved-addresses.sheets.remove-address.view :as remove-address]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[{:keys [name full-address chain-short-names address] :as opts}]
(let [open-send-flow (rn/use-callback
(let [[_ splitted-address] (network-utils/split-network-full-address address)
open-send-flow (rn/use-callback
#(rf/dispatch [:wallet/select-send-address
{:address full-address
:recipient full-address
:recipient {:label (utils/get-shortened-address
splitted-address)
:recipient-type :saved-address}
:stack-id :wallet-select-address
:start-flow? true}])
[full-address])
@@ -52,11 +56,10 @@
open-remove-confirmation-sheet (rn/use-callback
#(rf/dispatch
[:show-bottom-sheet
{:theme :dark
:shell? true
:blur-background colors/bottom-sheet-background-blur
:content (fn []
[remove-address/view opts])}])
{:theme :dark
:shell? true
:content (fn []
[remove-address/view opts])}])
[opts])
open-show-address-qr (rn/use-callback
#(rf/dispatch [:open-modal
@@ -73,27 +73,34 @@
(defn- filtered-list
[{:keys [search-text]}]
[rn/flat-list
{:key-fn :address
:data (rf/sub [:wallet/filtered-saved-addresses search-text])
:render-fn saved-address
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps :always
:content-container-style {:flex-grow 1}
:empty-component [empty-result]}])
(let [search-result (rf/sub [:wallet/filtered-saved-addresses search-text])]
(if (empty? search-result)
[empty-result]
[rn/flat-list
{:key-fn :address
:data search-result
:render-fn saved-address
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps :always
:content-container-style {:flex-grow 1}
:bounces false
:over-scroll-mode :never}])))
(defn- unfiltered-list
[{:keys [grouped-saved-addresses]}]
[rn/section-list
{:key-fn :title
:shows-vertical-scroll-indicator false
:sticky-section-headers-enabled false
:keyboard-should-persist-taps :always
:render-section-header-fn header
:sections grouped-saved-addresses
:render-fn saved-address
:content-container-style {:flex-grow 1}
:empty-component [empty-list]}])
(if (empty? grouped-saved-addresses)
[empty-list]
[rn/section-list
{:key-fn :title
:shows-vertical-scroll-indicator false
:sticky-section-headers-enabled false
:keyboard-should-persist-taps :always
:render-section-header-fn header
:sections grouped-saved-addresses
:render-fn saved-address
:bounces false
:over-scroll-mode :never
:content-container-style {:flex-grow 1}}]))
(defn- navigate-back
[]
@@ -2,7 +2,6 @@
(:require [quo.core :as quo]
[react-native.safe-area :as safe-area]
[status-im.contexts.settings.wallet.wallet-options.style :as style]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -16,16 +15,14 @@
(defn basic-settings-options
[]
[(when (ff/enabled? ::ff/settings.keypairs-and-accounts)
{:title (i18n/label :t/keypairs-and-accounts)
:blur? true
:on-press open-keypairs-and-accounts-settings-modal
:action :arrow})
(when (ff/enabled? ::ff/settings.saved-addresses)
{:title (i18n/label :t/saved-addresses)
:blur? true
:on-press open-saved-addresses-settings-modal
:action :arrow})])
[{:title (i18n/label :t/keypairs-and-accounts)
:blur? true
:on-press open-keypairs-and-accounts-settings-modal
:action :arrow}
{:title (i18n/label :t/saved-addresses)
:blur? true
:on-press open-saved-addresses-settings-modal
:action :arrow}])
(defn basic-settings
[]
@@ -74,7 +71,5 @@
[quo/page-top
{:title (i18n/label :t/wallet)
:title-accessibility-label :wallet-settings-header}]
(when (or (ff/enabled? ::ff/settings.keypairs-and-accounts)
(ff/enabled? ::ff/settings.saved-addresses))
[basic-settings])
[basic-settings]
[advanced-settings]]))
@@ -1,26 +1,33 @@
(ns status-im.contexts.shell.qr-reader.sheets.scanned-wallet-address
(:require
[quo.core :as quo]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[address]
[:<>
[quo/drawer-top
{:title address
:type :address}]
[quo/action-drawer
[[{:icon :i/send
:accessibility-label :send-asset
:label (i18n/label :t/send-to-this-address)
:on-press (fn []
(rf/dispatch [:wallet/select-send-address
{:address address
:recipient address
:stack-id :wallet-select-address
:start-flow? true}]))}
{:icon :i/save
:accessibility-label :save-address
:label (i18n/label :t/save-address)
:on-press #(js/alert "feature not implemented")}]]]])
(let [[_ splitted-address] (network-utils/split-network-full-address address)]
[:<>
[quo/drawer-top
{:title address
:type :address}]
[quo/action-drawer
[[{:icon :i/send
:accessibility-label :send-asset
:label (i18n/label :t/send-to-this-address)
:on-press (fn []
(rf/dispatch [:wallet/select-send-address
{:address address
:recipient {:recipient-type :address
:label (utils/get-shortened-address
splitted-address)}
:stack-id :wallet-select-address
:start-flow? true}]))}
(when (ff/enabled? :ff/wallet.saved-addresses)
{:icon :i/save
:accessibility-label :save-address
:label (i18n/label :t/save-address)
:on-press #(js/alert "feature not implemented")})]]]]))
+1 -1
View File
@@ -34,7 +34,7 @@
:WakuV2Config {;; Temporary fix until https://github.com/status-im/status-go/issues/3024
;; is resolved
:Nameserver "8.8.8.8"
:LightClient false}
:LightClient true}
:ShhextConfig {:VerifyTransactionURL config/verify-transaction-url
:VerifyENSURL config/verify-ens-url
:VerifyENSContractAddress config/verify-ens-contract-address
@@ -70,7 +70,15 @@
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
{keypair-name :name
keypair-type :type} (rf/sub [:wallet/current-viewing-account-keypair])
networks (rf/sub [:wallet/network-preference-details])]
networks (rf/sub [:wallet/network-preference-details])
origin-type (case keypair-type
:seed
:recovery-phrase
:key
:private-key
:default-keypair)]
[rn/scroll-view
{:style style/about-tab
:content-container-style {:padding-bottom (+ constants/floating-shell-button-height 8)}}
@@ -89,7 +97,7 @@
:on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])}]
(when (not watch-only?)
[quo/account-origin
{:type (if (= keypair-type "seed") :recovery-phrase :default-keypair)
{:type origin-type
:stored :on-device
:profile-picture (profile.utils/photo profile)
:customization-color customization-color
@@ -16,12 +16,13 @@
(rf/dispatch [:wallet/get-collectible-details id]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details]}]
[{:keys [preview-url collectible-details id]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:name (:name collectible-details)
:image (:uri preview-url)}])}]))
:image (:uri preview-url)
:id id}])}]))
(defn- on-end-reached
[]
@@ -5,6 +5,7 @@
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.data-store :as data-store]
[taoensso.timbre :as log]
[utils.collection]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as transforms]))
@@ -12,9 +13,11 @@
(defn get-keypairs-success
[{:keys [db]} [keypairs]]
(let [parsed-keypairs (data-store/rpc->keypairs keypairs)
default-key-uid (:key-uid (some #(when (= (:type %) :profile) %) parsed-keypairs))]
default-key-uid (->> parsed-keypairs
(some #(when (= (:type %) :profile) %))
:key-uid)]
{:db (-> db
(assoc-in [:wallet :keypairs] parsed-keypairs)
(assoc-in [:wallet :keypairs] (utils.collection/index-by :key-uid parsed-keypairs))
(assoc-in [:wallet :ui :create-account :selected-keypair-uid] default-key-uid))}))
(rf/reg-event-fx :wallet/get-keypairs-success get-keypairs-success)
@@ -41,10 +44,10 @@
(defn seed-phrase-validated
[{:keys [db]} [seed-phrase key-uid on-error]]
(let [keypair-already-added? (->> db
:wallet
:keypairs
(some #(= key-uid (:key-uid %))))]
(let [keypair-already-added? (-> db
:wallet
:keypairs
(contains? key-uid))]
(if keypair-already-added?
(do
(on-error)
@@ -121,7 +124,7 @@
:on-success on-success
:on-error (fn [error]
(log/error
"Failed to resolve next path derivation path"
"Failed to resolve next derivation path"
{:event :wallet/next-derivation-path
:method "accounts_resolveSuggestedPathForKeypair"
:error error
@@ -188,7 +191,7 @@
(rf/reg-event-fx
:wallet/derive-address-and-add-account
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences]}]]
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences key-uid]}]]
{:fx [[:json-rpc/call
[{:method "wallet_getDerivedAddresses"
:params [(security/safe-unmask-data password)
@@ -196,9 +199,10 @@
[derivation-path]]
:on-success (fn [[derived-account]]
(rf/dispatch [:wallet/add-account
(assoc account-preferences :password password)
(assoc account-preferences
:key-uid key-uid
:password password)
derived-account]))
:on-error #(log/info "Failed to get derived addresses"
derived-from-address
%)}]]]}))
:on-error [:wallet/log-rpc-error
{:event :wallet/derive-address-and-add-account
:params [derived-from-address [derivation-path]]}]}]]]}))
@@ -73,7 +73,7 @@
[]
(let [compressed-key (rf/sub [:profile/compressed-key])
customization-color (rf/sub [:profile/customization-color])
keypairs (rf/sub [:wallet/keypairs])
keypairs (rf/sub [:wallet/keypairs-list])
selected-keypair (rf/sub [:wallet/selected-keypair-uid])
profile-picture (rf/sub [:profile/image])
[selected-key-uid set-selected-key-uid] (rn/use-state selected-keypair)]
@@ -105,8 +105,7 @@
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/confirm-account-origin)
:button-one-props {:disabled? (= selected-keypair selected-key-uid)
:customization-color customization-color
:button-one-props {:customization-color customization-color
:on-press #(rf/dispatch [:wallet/confirm-account-origin
selected-key-uid])}
:container-style style/bottom-action-container}]]))
@@ -48,7 +48,6 @@
:action-props {:on-press #(rf/dispatch [:standard-auth/authorize
{:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/continue)}])
:button-text (i18n/label :t/edit)
:icon-left :i/face-id
:alignment :flex-start}
@@ -70,7 +69,7 @@
:icon-only? true
:on-press #(rf/dispatch [:emoji-picker/open {:on-select on-select-emoji}])
:container-style style/reaction-button-container}
:i/reaction]])
:i/edit]])
(defn- input
[_]
@@ -217,6 +216,7 @@
[:wallet/derive-address-and-add-account
{:password password
:derived-from-address derived-from
:key-uid key-uid
:derivation-path @derivation-path
:account-preferences preferences}])))
[derived-from])]
@@ -231,7 +231,7 @@
{:account-color @account-color
:slide-button-props {:on-auth-success on-auth-success
:disabled? (or (empty? @account-name)
(= "" @derivation-path)
(string/blank? @derivation-path)
(some? error))}}
[avatar
{:account-color @account-color
@@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.collectible.events
(:require [camel-snake-kebab.extras :as cske]
[react-native.platform :as platform]
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
@@ -200,25 +201,35 @@
(rf/reg-event-fx :wallet/trigger-share-collectible
(fn [_ [{:keys [title uri]}]]
{:fx [[:effects.share/open
{:title title
:message title
:url uri}]]}))
{:fx [[:dispatch
[:open-share
{:options (if platform/ios?
{:activityItemSources
[{:placeholderItem {:type :text
:content uri}
:item {:default {:type :url
:content uri}}
:linkMetadata {:title title}}]}
{:title title
:subject title
:url uri
:isNewTask true})}]]]}))
(rf/reg-event-fx :wallet/share-collectible
(fn [_ [{:keys [title uri in-sheet?]}]]
(if in-sheet?
(fn [{:keys [db]} [{:keys [title token-id contract-address chain-id]}]]
(let [uri (collectible-utils/get-opensea-collectible-url
{:chain-id chain-id
:token-id token-id
:contract-address contract-address
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
:is-goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])})]
{:fx [[:dispatch
[:hide-bottom-sheet]]
[:dispatch-later
{:ms 600
:dispatch [:wallet/trigger-share-collectible
{:title title
:uri uri}]}]]}
{:fx [[:dispatch
[:wallet/trigger-share-collectible
{:title title
:uri uri}]]]})))
:uri uri}]}]]})))
(rf/reg-event-fx
:wallet/navigate-to-opensea

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