Compare commits

...
Author SHA1 Message Date
Andrea Maria Piana c038e059d3 enable light client by default 2024-07-10 08:24:30 +01:00
Mohsen 3521421098 [#20543] fix: incorrect black background behind floating button (#20585) 2024-07-09 21:12:18 +03:30
Omar Basem f70a743a8c Fix(wallet): address validation (#20674)
* fix(wallet): address validation (#20674)
2024-07-09 15:59:48 +04:00
NikolayandJamie Caprani a2178951d7 chore(wallet): import private key - backend integration
Co-authored-by: Jamie Caprani <jamiecaprani@gmail.com>
2024-07-09 03:49:31 -07:00
Ulises Manuel 7774c4eac1 fix(wallet): Improve collectible UX and fix data displayed (#20657)
* Add variant unknown variant for collectibles

* Fix blank collectibles listed

* Improve `expanded-collectible` animation and add support for different gradient-colors

* Make :wallet/collectible-details-owner subscription depend on `wallet/accounts` instead of `:wallet`

* Make collectible tabs component more flexible

* Remove now unused subscriptions

* Improve UX navigation to collectible detail page

* Pass the current collectible gradient-color when a collectible is pressed

* Fix tests
2024-07-08 14:19:01 -06:00
Alexander 4c4a8b65d4 Add QR scanner to connect Dapps through Connected Dapps screen (#20647)
* Add QR scanner to connect Dapps through Connected Dapps screen

* Style fix

* use-mount
2024-07-08 13:55:32 +02:00
Parvesh Monu de6d9a6c3b chore: remove hot reload while theme changing (#20663) 2024-07-08 14:51:27 +05:30
Mohsen da16d1f69e [#20571] fix: cleanup save address on mount (#20650) 2024-07-08 12:27:16 +03:30
John Ngei a13975f3f6 fix the warning message when the user enters the wrong password (#20605) 2024-07-06 00:15:36 +02:00
Icaro Motta c473b8c9b1 chore(settings): Add boilerplate for the new Privacy and security screen (#20668) 2024-07-05 14:07:01 -03:00
Parvesh Monu 1f333cc937 fix wallet send flow wrong status bar color on select assets screen (#20662) 2024-07-05 20:57:20 +05:30
Yevheniia Berdnyk 460aaedbca e2e: false failures fixes 2024-07-05 16:25:12 +03:00
mmilad75 66639fc3ed fix(wallet): fix checkbox (#19756) 2024-07-05 13:33:15 +01:00
Mohsen 2cc689a896 [#20638] fix: Scan missing keypair keep scanning after success attempt (#20640) 2024-07-05 14:33:38 +03:30
Ajay Sivan b4866ff728 Swap: Edit slippage drawer (#20554) 2024-07-05 02:44:38 -07:00
Sean Hagstrom eaa5016094 feat: add support for updating key-pairs and accounts from app signal (#20550)
This change adds support for processing app signals for syncing changes when adding, editing, or removing keypairs, accounts, and watch-only accounts.
2024-07-04 16:25:30 +01:00
Sean Hagstrom 66f77e1467 fix: configure selectable key-pair to use box-only for pointer-events (#20611)
This change attempts to only to override the default `pointer-events` behaviour for the `quo/keypair` component when the component uses the `selector` action. Now when the `quo/keypair` component is rendered with a selector, only the top-level view of the component will be pressable. And when the `quo/keypair` component is rendered without a selector it will allow for the children of the component to be pressable too.
2024-07-04 15:48:45 +01:00
Volodymyr Kozieiev d16c1a3c85 Disable possibility to changes amounts to send (#20639) 2024-07-04 15:02:57 +01:00
Mohamed Javid a049fd341e chore(docs)_: include new status-go tagging command in the merging PR process (#20607)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-07-04 15:37:27 +05:30
Volodymyr Kozieiev 140fa3115c Add possibility to edit networks list when routes not found (#20642) 2024-07-04 10:54:17 +01:00
Siddarth Kumar 147676ae8c chore: add Xcode 15.4 to allowed versions (#20641)
This commit adds Xcode 15.4 to allowed versions in xcode-wrapper overlay.
2024-07-04 14:39:23 +05:30
Ulises Manuel 1e40d49369 feat(wallet): Add modal to remove :key and :seed accounts (#20569) 2024-07-03 11:48:10 -06:00
BalogunofAfrica b17f2892c7 feat: collectibles details loading (#20400) 2024-07-03 15:49:12 +01:00
Volodymyr Kozieiev b28a8e153e Fixes for screen where user locks network amounts to send (#20519) 2024-07-03 15:17:29 +01:00
Alexander 35a1905396 Fix auth slider resetting when wallet connect signing is finished (#20589)
* Fix auth slider resetting when wallet connect signing is finished

* Lint fix

* Fixes

* Fixes
2024-07-03 15:27:27 +02:00
Brian Sztamfater 2e8776d0a6 feat(swap): implement network selection drawer (#20368) 2024-07-03 09:15:07 -03:00
Alexander 99506c810d Re-hide connected dapps screen behind a feature flag (#20627)
* Connected dapps screen is not hidden behind a feature flag

* Style fix
2024-07-03 13:01:24 +02:00
jakub e83f6ff445 fix(ci): add missing import for JsonBuilder
Signed-off-by: Jakub Sokołowski <jakub@status.im>
2024-07-03 12:21:39 +02:00
Lungu Cristian f51f52ec27 Fix WalletConnect transactions (#20608)
* fix: sign-transaction

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

* fix: sendTranasaction not working

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

* ref: removing 0x from the signature

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

* ref: tx data from responding to processing events

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

* fix: request dapp subscription

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

* fix: tx data bug

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>

---------

Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>
2024-07-03 12:13:13 +02:00
Parvesh Monu e58e2209bb fix endless loading skeleton for some empty channels on IOS (#20602) 2024-07-03 15:26:43 +05:30
Parvesh Monu 8aa1cadc66 fix chat screen design issues (#20621) 2024-07-03 13:02:11 +05:30
Icaro Motta 91c22df498 Remove all integrations with signal wakuv2.peerstats (#20501)
Removes code integrating with the signal wakuv2.peerstats. The response from
this signal is rather large and it can sometimes happen in short bursts.

- Fixes https://github.com/status-im/status-mobile/issues/20176

We were using it to keep track of the number of peers in real-time. We now only
fetch the peer count in two instances (synchronously inside rn/use-mount):

- When the user opens the legacy screen Settings > Advanced > Peers stats.
- When the user opens the visibility status dropdown in Settings, because the
  peers count will be used when the user chooses "Offline" (status inactive).

Note: we don't send anymore the peers count when the user shakes the phone. We
assume this value is already available in :peers-summary (which will be shared
by the user).

status-go still publishes the signal, we just ignore it to remove the
performance overhead of transforming to cljs and mutating the app-db (thus
interrupting the queue from more important stuff).

Steps to test:

- Verify user can see peers count in Settings > Advanced > Peers stats
- Verify changing the visibility status of user Alice in the Settings screen
  leads to the desired effect to the other party seeing Alice's visibility
  status.
2024-07-02 19:48:15 -03:00
Ulises Manuel e221e23255 fix(wallet): Validation of addresses in send-to screen (#20570)
* Fix validation of addresses in send-to screen
2024-07-02 13:57:31 -06:00
Yevheniia Berdnyk e8e05e58e0 e2e: update for Syncing view 2024-07-02 18:30:06 +03:00
Lungu Cristian ac4ffd83db Wallet Connect session establish networks (#20576)
* feat: showing supported networks in wc connection

* feat: added :large size for quo/data-item

* feat: added required networks check
2024-07-02 16:39:33 +02:00
Shivek KhuranaandLungu Cristian b021b1e20a 🎛️ Account switcher UI for Wallet Connect sessions (#20573)
* 🎛️ Account switcher UI for Wallet Connect sessions

* 😢 Remove repl workflow

* 🔀 Merge current-proposal request and account

*  Remove redundant test

* 🐛 Lint fix

---------

Co-authored-by: Lungu Cristian <lungucristian95@gmail.com>
2024-07-02 18:48:48 +05:30
Ajay Sivan b650591e58 Refactor - Info/Info Message component (#20551) 2024-07-02 04:06:37 -07:00
Mohamed Javid 0581fc2f9d feat(wallet): sync saved addresses (#20546)
This commit adds syncing saved addresses across paired devices whenever a new saved address is added or an existing one is edited or removed.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-07-02 15:33:54 +05:30
yqrashawn ef9cc55501 feat: check before syncing doc (#20504) 2024-07-02 16:36:42 +08:00
Yevheniia Berdnyk 3b3a39e37b e2e: fixes for community,wallet and removed outdated xfails 2024-07-02 01:50:29 +03:00
Icaro Motta b255874e95 fix(communities)_: Buggy scroll behavior in community channel member list (#20517)
Fixes the scroll behavior in a community channel member list. The problem was
that the code wasn't enforcing the correct height.

Partially solves https://github.com/status-im/status-mobile/issues/20514

Steps to test: Long press on any community channel and press View channel
members and details. The user should be able to correctly scroll throughout the
entire list of members.
2024-07-01 18:55:24 -03:00
Icaro Motta 1c83916fc3 fix: Make BigNumber comparator safe against unsupported data types (#20614)
BigNumber instances are not comparable to other data types, except numbers and
strings (supported directly by the library). This commit makes = safe on
bignumbers (no exceptions should be thrown), even when comparing a bignumber
with a nil value.

There's another important benefit from having a custom comparator: performance,
because re-frame will be able to correctly compare data with bignumbers and thus
reuse cached subscriptions and also Reagent will be able to skip processing when
props are equal.

The IComparable interface was not changed. Similarly to core CLJS data types,
sorting heterogeneous collections throws (ignore nils).

```clojure
;; This throws with message: cannot compare 10 to foo
(sort ["foo" 10])
```

We could make sorting work with heterogeneous collections, but then we would
need to extend many core data types to play nice with BigNumber and that sounds
more like a hack, and it's also not a problem we have nowadays.
2024-07-01 18:38:10 -03:00
jakub 31acf51b1e feat(ci): use s5cmd instead of obsolete s3cmd
It's actively maintained and has better concurrency support.

Depends on:
- https://github.com/status-im/status-jenkins-lib/pull/92

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2024-07-01 16:31:29 +02:00
Parvesh Monu 424d2d4b5c fix can't pair with dApp on android with WalletConnect (#20600) 2024-07-01 18:01:58 +05:30
179 changed files with 3571 additions and 1557 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -71,7 +71,7 @@ pipeline {
}
stage('Upload') {
steps { script {
def urls = apks.collect { s3.uploadArtifact(it) }
def urls = apks.collect { s5cmd.upload(it) }
if (urls.size() > 1) { /* Return only the universal APK. */
env.PKG_URL = urls.find { it.contains('universal') }
} else { /* If no universal is available pick first. */
+24 -3
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
import groovy.json.JsonBuilder
pipeline {
agent { label 'linux' }
@@ -72,7 +74,7 @@ pipeline {
iOS: utils.pkgUrl(ios),
Diawi: utils.getEnv(ios, 'DIAWI_URL'),
/* upload the sha256 checksums file too */
SHA: s3.uploadArtifact(sha),
SHA: s5cmd.upload(sha),
]
/* add URLs to the build description */
jenkins.setBuildDesc(urls)
@@ -83,7 +85,7 @@ pipeline {
steps { script {
switch (utils.getBuildType()) {
case 'nightly': /* Create JSON file with newest build URLs */
s3.updateBucketJSON(urls, 'latest.json');
updateBucketJSON(urls, 'latest.json');
break;
case 'release':
github.publishReleaseFiles(repo: 'status-mobile');
@@ -114,3 +116,22 @@ def Boolean getPublishDefault(Boolean previousValue) {
if (previousValue != null) { return previousValue }
return false
}
/* Helper for updating JSON with newest builds. */
def updateBucketJSON(urls, fileName) {
/* latest.json has slightly different key names */
def content = [
DIAWI: urls.Diawi,
APK: urls.Apk, IOS: urls.iOS,
APP: urls.App, MAC: urls.Mac,
WIN: urls.Win, SHA: urls.SHA
]
def filePath = "${pwd()}/pkg/${fileName}"
/* it might not exist */
sh "mkdir -p ${pwd()}/pkg"
def contentJson = new JsonBuilder(content).toPrettyString()
println "${filePath}:\n${contentJson}"
writeFile(file: filePath, text: contentJson)
return s5cmd.upload(filePath)
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -75,7 +75,7 @@ pipeline {
stage('Upload') {
steps {
script {
env.PKG_URL = s3.uploadArtifact(LOG_FILE)
env.PKG_URL = s5cmd.upload(LOG_FILE)
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'macos' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label params.AGENT_LABEL }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent {
+5 -3
View File
@@ -32,14 +32,16 @@ status-mobile code that makes it to the `develop` branch, should always point to
In practice, this means that sometimes they need to be merged in lockstep.
1) Create a PR in status-go and status-mobile. Update the status-go version to the PR revision `scripts/update-status-go.sh $git_revision`.
2) Get both PRs reviewed and approved. Once status-mobile PR has been approved, go through manual QA testing if necessary. Don't merge status-mobile PR just yet.
3) Now that you know the integration between client & server is working, bump the `VERSION` in status-go and merge it.
4) Once merged, tag the version with the new version and push the tag:
3) Now that you know the integration between client & server is working, merge the status-go PR first.
4) Once merged, tag the merged commit with the new version and push the tag:
```
git checkout develop
git pull develop
git tag vx.y.z
make tag-version
git push origin vx.y.z
```
:warning: If a specific commit need to tagged in status-go, use `make tag-version TARGET_COMMIT={hash}`. More info about tagging in [status-go](https://github.com/status-im/status-go/blob/develop/RELEASING.md#tagging-versions).
5) Update status-mobile with the new status-go version, using the new tag `scripts/update-status-go.sh "vx.y.z"`
6) If you had to rebase status-go to include new changes, e2e test MUST be re-run. If there's any issue you will
have to fix in status-go with another PR and follow the same process.
+2 -2
View File
@@ -31,7 +31,7 @@ NOW:
(defn view
[{:keys [on-press on-long-press icon]}]
(let [[pressed? set-pressed] (rn/use-state false)
theme (theme/use-theme-value)
theme (theme/use-theme)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
@@ -47,7 +47,7 @@ NOW:
- We no longer need to create an anonymous function for rendering. This removes unnecessary confusion and the need for specific knowledge on how it works and why it was needed.
- `rn/use-state` is used instead of `reagent/atom`
- State values no longer need to be dereferenced; they are accessible as regular symbols. This eliminates a common bug where the "@" symbol was inadvertently omitted.
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme-value)` hook can be used directly in the components
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme)` hook can be used directly in the components
- `:f>` not needed anymore, all components are functional by default
- `rn/use-callback` hook should be used for anon callback functions
+1 -1
View File
@@ -57,7 +57,7 @@ in {
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
openjdk = super.openjdk11_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
versions = ["15.1" "15.2" "15.3"];
versions = ["15.1" "15.2" "15.3" "15.4"];
};
go = super.go_1_21;
clang = super.clang_15;
+3 -2
View File
@@ -20,9 +20,10 @@
"@react-native-community/netinfo": "^4.4.0",
"@react-native-community/push-notification-ios": "^1.4.1",
"@react-native-community/slider": "^3.0.0",
"@walletconnect/react-native-compat": "^2.12.2",
"@walletconnect/web3wallet": "^1.11.2",
"@walletconnect/react-native-compat": "2.11.2",
"@walletconnect/web3wallet": "1.10.2",
"base-64": "^1.0.0",
"big-integer": "1.6.51",
"bignumber.js": "git+https://github.com/status-im/bignumber.js.git#refs/tags/v4.0.2-status",
"chance": "^1.1.0",
"emojilib": "^2.4.0",
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+1 -2
View File
@@ -108,8 +108,7 @@
(when (and (multiaccounts.model/logged-in? db)
(= current-theme-type status-im.constants/theme-type-system))
{:profile.settings/switch-theme-fx
[(get-in db [:profile/profile :appearance])
(:view-id db) true]})))
[(get-in db [:profile/profile :appearance]) (:view-id db)]})))
(defn- on-biometric-auth-fail
[{:keys [code]}]
+1 -1
View File
@@ -17,7 +17,7 @@
(reg-root-key-sub :ui/search :ui/search)
(reg-root-key-sub :network/type :network/type)
(reg-root-key-sub :network-status :network-status)
(reg-root-key-sub :peers-count :peers-count)
(reg-root-key-sub :peer-stats/count :peer-stats/count)
(reg-root-key-sub :peers-summary :peers-summary)
(reg-root-key-sub :web3-node-version :web3-node-version)
@@ -1,14 +1,9 @@
(ns legacy.status-im.ui.components.connectivity.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.animation :as animation]
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[utils.i18n :as i18n])
(:require-macros [legacy.status-im.utils.views :as views :refer [defview letsubs]]))
[legacy.status-im.ui.components.react :as react])
(:require-macros [legacy.status-im.utils.views :as views]))
(defn easing
[direction n]
@@ -72,112 +67,3 @@
colors/white)
:left
(* 0.15 parent-width))}]]]))
(defview loading-indicator
[]
(letsubs [fetching? [:mailserver/fetching?]
window-width [:dimensions/window-width]]
(when fetching?
[loading-indicator-anim window-width])))
(defn hide-sheet-and-dispatch
[event]
(re-frame/dispatch [:bottom-sheet/hide-old])
(re-frame/dispatch event))
(defview connectivity-sheet
[]
(letsubs [{:keys [peers node mobile sync]} [:connectivity/state]
current-mailserver-name [:mailserver/current-name]
peers-count [:peers-count]
{:keys [syncing-on-mobile-network?]} [:profile/profile]]
[:<>
[quo/header {:title (i18n/label :t/connection-status) :border-bottom false}]
[quo/list-header (i18n/label :t/peer-to-peer)]
(if (= peers :offline)
[list.item/list-item
{:title (i18n/label :t/not-connected-to-peers)
:accessibility-label "not-connected-to-peers"
:subtitle (i18n/label :t/unable-to-send-messages)
:subtitle-max-lines 2
:theme :negative
:icon :main-icons/network}]
[list.item/list-item
{:title (str (i18n/label :t/connected-to)
" " peers-count
" " (string/lower-case (i18n/label :t/peers)))
:accessibility-label "connected-to-n-peers"
:subtitle (i18n/label :t/can-send-messages)
:subtitle-max-lines 2
:theme :positive
:icon :main-icons/network}])
[quo/list-header (i18n/label :t/history-nodes)]
(cond
(#{:error :offline} node)
[list.item/list-item
{:title (i18n/label :t/not-connected-nodes)
:accessibility-label "not-connected-nodes"
:subtitle (i18n/label :t/unable-to-fetch)
:theme :negative
:icon :main-icons/mailserver}]
(= node :disabled)
[list.item/list-item
{:title (i18n/label :t/nodes-disabled)
:accessibility-label "nodes-disabled"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(and mobile (not sync))
[list.item/list-item
{:title (i18n/label :t/waiting-wi-fi)
:accessibility-label "waiting-wi-fi"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(= node :connecting)
[list.item/list-item
{:title (i18n/label :t/connecting)
:accessibility-label "connecting"
:subtitle (i18n/label :t/unable-to-fetch)
:icon :main-icons/mailserver}]
(= node :online)
[list.item/list-item
{:title (str (i18n/label :t/connected-to) " " current-mailserver-name)
:accessibility-label "connected-to-mailserver"
:subtitle (i18n/label :t/you-can-fetch)
:theme :positive
:icon :main-icons/mailserver}])
[list.item/list-item
{:title (i18n/label :t/settings)
:accessibility-label "settings"
:theme :accent
:on-press #(hide-sheet-and-dispatch [:navigate-to :legacy-sync-settings])
:icon :main-icons/settings}]
(when mobile
[:<>
[react/view
{:margin-vertical 8
:background-color colors/gray-lighter
:height 36
:align-items :center
:justify-content :center}
[react/text {:style {:color colors/gray}} (i18n/label :t/youre-on-mobile-network)]]
[list.item/list-item
{:title (i18n/label :t/mobile-network-use-mobile)
:accessibility-label "mobile-network-use-mobile"
:accessory :switch
:on-press #(re-frame/dispatch [:mobile-network/set-syncing
(not syncing-on-mobile-network?)])
:active syncing-on-mobile-network?}]
[react/text {:style {:margin-horizontal 16 :margin-bottom 12 :color colors/gray}}
(i18n/label :t/status-mobile-descr)]])]))
(defn get-icon
[{:keys [peers node mobile sync]}]
(if (or (= peers :offline)
(= node :offline)
(= node :connecting))
:main-icons/offline
(if mobile
(if sync :main-icons/mobile-sync :main-icons/mobile-sync-off)
(when (#{:error :disabled} node) :main-icons/node-offline))))
@@ -1,17 +1,21 @@
(ns legacy.status-im.ui.screens.peers-stats
(:require
[react-native.core :as react-native.core]
[react-native.core :as rn]
[utils.i18n :as i18n]
[utils.re-frame :as re-frame]))
[utils.re-frame :as rf]))
(defn peers-stats
[]
(let [peers-count (re-frame/sub [:peers-count])]
[react-native.core/view
{:flex 1
:margin-horizontal 8}
[react-native.core/view
(let [peers-count (rf/sub [:peer-stats/count])]
(rn/use-mount
(fn []
(rf/dispatch [:peer-stats/get-count])))
[rn/view
{:style {:flex 1
:margin-horizontal 8}}
[rn/view
{:style {:flex-direction :row
:margin-vertical 8
:justify-content :space-between}}
[react-native.core/text (str (i18n/label :t/peers-count) ": " peers-count)]]]))
[rn/text (str (i18n/label :t/peers-count) ": " peers-count)]]]))
@@ -128,7 +128,6 @@
:current-chat-id
:network
:network-status
:peers-count
:peers-summary
:sync-state
:view-id
@@ -130,7 +130,7 @@
status-type]}]
(and
(= status-type constants/visibility-status-inactive)
(> (:peers-count db) 0))
(pos? (:peer-stats/count db)))
;; Disable broadcasting further updates
(conj {:ms 1000
:dispatch
@@ -2,7 +2,7 @@
(:require
[quo.components.buttons.button.view :as button]
[quo.components.buttons.predictive-keyboard.style :as style]
[quo.components.info.info-message :as info-message]
[quo.components.info.info-message.view :as info-message]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
@@ -57,17 +57,17 @@
:key-fn str}]
:error
[info-message/info-message
{:icon :i/info
:size :default
:type :error}
[info-message/view
{:icon :i/info
:size :default
:status :error}
text]
:info
[info-message/info-message
(merge {:icon :i/info
:size :default
:type (if (= type :error) :error :default)}
[info-message/view
(merge {:icon :i/info
:size :default
:status (if (= type :error) :error :default)}
(when blur?
{:text-color colors/white-opa-70
:icon-color colors/white-opa-40}))
@@ -26,7 +26,8 @@
(reanimated/set-shared-value x-pos clamped-x)
(when (and reached-end? (not sliding-complete?))
(set-sliding-complete true)
(when on-complete (on-complete reset-fn))))))
(when on-complete
(on-complete reset-fn))))))
(gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)]
@@ -54,9 +55,10 @@
on-track-layout (rn/use-callback
#(set-track-width (oops/oget % "nativeEvent.layout.width")))
reset-fn (rn/use-callback
(fn []
(fn [keep-at-end-after-slide?]
(set-sliding-complete false)
(animations/reset-track-position x-pos)))
(when-not keep-at-end-after-slide?
(animations/reset-track-position x-pos))))
dimensions (rn/use-callback
(partial utils/get-dimensions
(or track-width constants/default-width)
-48
View File
@@ -1,48 +0,0 @@
(ns quo.components.info.info-message
(:require
[quo.components.icon :as quo.icons]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn get-color
[k theme]
(case k
:success (colors/resolve-color :success theme)
:error (colors/resolve-color :danger theme)
:warning (colors/resolve-color :warning theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn info-message
"[info-message opts \"message\"]
opts
{:type :default/:success/:error
:size :default/:tiny
:icon :i/info ;; info message icon
:text-color colors/white ;; text color override
:icon-color colors/white ;; icon color override
:no-icon-color? false ;; disable tint color for icon"
[{:keys [type size icon text-color icon-color no-icon-color? style accessibility-label
container-style]} message]
(let [theme (quo.theme/use-theme)
weight (if (= size :default) :regular :medium)
icon-size (if (= size :default) 16 12)
size (if (= size :default) :paragraph-2 :label)
text-color (or text-color (get-color type theme))
icon-color (or icon-color text-color)]
[rn/view
{:style (merge {:flex-direction :row
:align-items :center}
style
container-style)}
[quo.icons/icon icon
{:color icon-color
:no-color no-icon-color?
:size icon-size}]
[text/text
{:accessibility-label accessibility-label
:size size
:weight weight
:style {:color text-color
:margin-horizontal 4}} message]]))
@@ -0,0 +1,32 @@
(ns quo.components.info.info-message.component-spec
(:require
[quo.components.info.info-message.view :as info-message]
[test-helpers.component :as h]))
(h/describe "Info: Info Message"
(h/test "basic render"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-label-text :info-message)))
(h/test "render with correct message"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-text "Message")))
(h/test "render icon"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-label-text :icon))))
@@ -0,0 +1,6 @@
(ns quo.components.info.info-message.style)
(def container
{:flex-direction :row
:gap 4
:align-items :center})
@@ -0,0 +1,53 @@
(ns quo.components.info.info-message.view
(:require [quo.components.icon :as icons]
[quo.components.info.info-message.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:status {:optional true} [:maybe [:enum :default :success :error :warning]]]
[:size {:optional true} [:maybe [:enum :default :tiny]]]
[:blur? {:optional true} [:maybe :boolean]]
[:icon :keyword]
[:color {:optional true} [:maybe :string]]
[:text-color {:optional true} [:maybe :string]]
[:icon-color {:optional true} [:maybe :string]]
[:no-icon-color? {:optional true} [:maybe :boolean]]
[:accessibility-label {:optional true} [:maybe :keyword]]
[:container-style {:optional true} [:maybe :map]]]]
[:message :string]]
:any])
(defn- get-color
[status theme blur?]
(case status
:success (if blur? colors/success-60 (colors/resolve-color :success theme))
:error (if blur? colors/danger-60 (colors/resolve-color :danger theme))
:warning (if blur? colors/warning-60 (colors/resolve-color :warning theme))
(if blur? colors/white-opa-40 (colors/theme-colors colors/neutral-50 colors/neutral-40 theme))))
(defn view-internal
[{:keys [status size blur? icon color icon-color text-color no-icon-color? container-style
accessibility-label]} message]
(let [theme (quo.theme/use-theme)
default-color (get-color status theme blur?)
text-color (or text-color color default-color)
icon-color (or icon-color color default-color)]
[rn/view {:style (merge style/container container-style)}
[icons/icon icon
{:size (if (= size :tiny) 12 16)
:color icon-color
:no-color? no-icon-color?}]
[text/text
{:size (if (= size :tiny) :label :paragraph-2)
:accessibility-label accessibility-label
:style {:color text-color}} message]]))
(def view (schema/instrument #'view-internal ?schema))
@@ -44,13 +44,14 @@
[:label :string]
[:fiat-value :string]
[:token-value :string]
[:container-style {:optional true} [:maybe :map]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:state {:optional true} [:enum :pressed :active :disabled :default]]
[:on-press {:optional true} [:maybe fn?]]]]]
:any])
(defn- view-internal
[{:keys [on-press state customization-color]
[{:keys [on-press container-style state customization-color]
:as props
:or {customization-color :blue}}]
(let [theme (quo.theme/use-theme)
@@ -59,7 +60,8 @@
on-press-out (rn/use-callback #(set-pressed false))
internal-state (if pressed? :pressed state)]
[rn/pressable
{:style (style/container internal-state customization-color theme)
{:style (merge (style/container internal-state customization-color theme)
container-style)
:on-press-in (when-not (= state :disabled) on-press-in)
:on-press-out (when-not (= state :disabled) on-press-out)
:on-press (when-not (= state :disabled) on-press)
+3 -3
View File
@@ -8,7 +8,7 @@
[quo.foundations.colors :as colors]
[react-native.core :as rn]))
(def container-style
(def container
{:margin-horizontal 8
:padding-vertical 8
:padding-horizontal 12
@@ -43,9 +43,9 @@
(defn user
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
untrustworthy? on-press on-long-press accessory customization-color theme
allow-multiple-presses? disabled?]}]
allow-multiple-presses? disabled? container-style]}]
[rn/touchable-highlight
{:style container-style
{:style (merge container container-style)
:underlay-color (colors/resolve-color customization-color theme 5)
:allow-multiple-presses? allow-multiple-presses?
:accessibility-label :user-list
@@ -11,7 +11,7 @@
(defn fallback
[{:keys [theme opacity]}]
[{:opacity opacity}
{:opacity default-opacity-for-image
{:opacity 1
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
@@ -60,8 +60,13 @@
:padding-right 0
:padding-top 4})
(def card-detail-text
{:flex 1})
(defn card-detail-text
[empty-name? theme]
{:flex 1
:margin-right 8
:color (if empty-name?
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
(colors/theme-colors colors/neutral-100 colors/white theme))})
(defn card-loader
[opacity]
@@ -115,6 +120,7 @@
[{:opacity opacity}
{:flex 1
:flex-direction :row
:column-gap 8
:opacity default-opacity-for-image}])
(defn supported-file
@@ -1,5 +1,6 @@
(ns quo.components.profile.collectible-list-item.view
(:require
[clojure.string :as string]
[quo.components.avatars.collection-avatar.view :as collection-avatar]
[quo.components.counter.collectible-counter.view :as collectible-counter]
[quo.components.icon :as icon]
@@ -21,7 +22,7 @@
(def cached-load-time 200)
(def error-wait-time 800)
(defn on-load-end
(defn animate-loading-image
[{:keys [load-time set-state loader-opacity image-opacity]}]
(reanimated/animate loader-opacity 0 timing-options-out)
(reanimated/animate image-opacity 1 timing-options-in)
@@ -34,6 +35,12 @@
(set-state (fn [prev-state]
(assoc prev-state :image-loaded? true)))))
(defn on-load
[evt set-state]
(let [source (.. evt -nativeEvent -source)
aspect-ratio (/ (.-width source) (.-height source))]
(set-state (fn [prev-state] (assoc prev-state :image-aspect-ratio aspect-ratio)))))
(defn on-load-error
[set-state]
(js/setTimeout (fn []
@@ -54,12 +61,12 @@
(assoc prev-state :avatar-loaded? true)))))
(defn- fallback-view
[{:keys [label theme image-opacity]}]
[reanimated/view
{:style (style/fallback {:opacity image-opacity
:theme theme})}
[{:keys [label theme image-opacity on-load-end]}]
(rn/use-mount on-load-end)
[reanimated/view {:style (style/fallback {:opacity image-opacity :theme theme})}
[rn/view
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
[icon/icon :i/sad
{:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
[rn/view {:style {:height 4}}]
[text/text
{:size :paragraph-2
@@ -87,31 +94,43 @@
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
(let [loader-opacity (reanimated/use-shared-value 1)
avatar-opacity (reanimated/use-shared-value 0)
[load-time set-load-time] (rn/use-state (datetime/now))]
[load-time set-load-time] (rn/use-state (datetime/now))
set-avatar-loaded (fn []
(on-load-avatar {:set-state set-state
:load-time load-time
:loader-opacity loader-opacity
:avatar-opacity avatar-opacity}))
empty-name? (string/blank? collectible-name)]
(rn/use-mount (fn []
(when (string/blank? avatar-image-src)
(set-avatar-loaded))))
[rn/view {:style style/card-details-container}
[reanimated/view {:style (style/avatar-container avatar-opacity)}
(if community?
[preview-list/view
{:type :communities
:size :size-20}
(cond
(string/blank? avatar-image-src)
[loading-square theme]
community?
[preview-list/view {:type :communities :size :size-20}
[avatar-image-src]]
:else
[collection-avatar/view
{:size :size-20
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-avatar {:set-state set-state
:load-time load-time
:loader-opacity loader-opacity
:avatar-opacity avatar-opacity})
:on-load-end set-avatar-loaded
:image avatar-image-src}])
[rn/view {:style {:width 8}}]
[text/text
{:size :paragraph-1
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:style style/card-detail-text}
collectible-name]]
(when (not (:avatar-loaded? state))
:style (style/card-detail-text empty-name? theme)}
(if empty-name?
(i18n/label :t/unknown)
collectible-name)]]
(when-not (:avatar-loaded? state)
[reanimated/view {:style (style/card-loader loader-opacity)}
[loading-square theme]
[loading-message theme]])]))
@@ -122,39 +141,44 @@
(let [theme (quo.theme/use-theme)
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
[load-time set-load-time] (rn/use-state (datetime/now))]
[load-time set-load-time] (rn/use-state (datetime/now))
set-image-loaded (fn []
(animate-loading-image {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity}))]
[rn/view {:style (style/card-view-container theme)}
[rn/view {:style {:aspect-ratio 1}}
(cond
(:image-error? state)
[fallback-view
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(:image-error? state) [fallback-view
{:image-opacity image-opacity
:on-load-end set-image-loaded
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(not supported-file?) [fallback-view
{:image-opacity image-opacity
:on-load-end set-image-loaded
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state)) [loading-image
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(not supported-file?)
[fallback-view
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state))
[loading-image
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(when supported-file?
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load #(on-load % set-state)
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-load-end set-image-loaded
:on-error #(on-load-error set-state)
:source image-src}]])]
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
(when (and (or (:image-loaded? state)
(not supported-file?))
(not (:image-error? state))
counter)
[collectible-counter/view
{:container-style style/collectible-counter
:size :size-24
@@ -197,11 +221,12 @@
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load #(on-load % set-state)
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-load-end #(animate-loading-image {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-error #(on-load-error set-state)
:source image-src}]])
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
@@ -219,12 +244,13 @@
(defn- view-internal
[{:keys [container-style type on-press on-long-press supported-file?]
:as props}]
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-error? false
:avatar-loaded? false})
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-aspect-ratio nil
:image-error? false
:avatar-loaded? false})
collectible-ready? (or (:image-loaded? state) (not supported-file?))]
[rn/pressable
{:on-press (when collectible-ready? on-press)
{:on-press (when collectible-ready? #(on-press (:image-aspect-ratio state)))
:on-long-press (when collectible-ready? on-long-press)
:accessibility-label :collectible-list-item
:style container-style}
@@ -1,10 +1,13 @@
(ns quo.components.profile.expanded-collectible.style
(:require [quo.foundations.colors :as colors]))
(def container
{:align-items :center
:justify-content :center
:border-radius 16})
(defn container
[aspect-ratio]
(cond-> {:align-items :center
:justify-content :center
:border-radius 16}
aspect-ratio (assoc :width "100%"
:aspect-ratio aspect-ratio)))
(defn image
[square? aspect-ratio theme]
@@ -25,18 +28,43 @@
:border-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)})
(defn fallback
[{:keys [theme]}]
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius 16
:width "100%"
:aspect-ratio 1
:align-items :center
:justify-content :center})
([theme]
(fallback theme 1))
([theme aspect-ratio]
{:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:border-width 1
:border-radius 16
:width "100%"
:aspect-ratio aspect-ratio
:align-items :center
:justify-content :center}))
(def counter
{:position :absolute
:top 12
:right 12})
(defn loading-image-with-opacity
[opacity]
[{:align-items :center
:aspect-ratio 1
:border-radius 16
:justify-content :center
:opacity opacity
:position :absolute
:width "100%"
:z-index 1}])
(defn gradient-view
[aspect-ratio]
{:border-radius 16
:width "100%"
:aspect-ratio aspect-ratio
:align-items :center
:justify-content :center})
(defn supported-file
[opacity]
{:opacity opacity})
@@ -1,17 +1,39 @@
(ns quo.components.profile.expanded-collectible.view
(:require
[clojure.string :as string]
[promesa.core :as promesa]
[quo.components.counter.collectible-counter.view :as collectible-counter]
[quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.components.profile.expanded-collectible.style :as style]
[quo.foundations.colors :as colors]
[quo.foundations.gradients :as gradients]
[quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[schema.core :as schema]
[utils.i18n :as i18n]))
(def loader-out 650)
(def image-in 1000)
(def error-wait-time 800)
(defn on-load-end
[{:keys [loader-opacity image-opacity]}]
(reanimated/animate loader-opacity 0 loader-out)
(reanimated/animate image-opacity 1 image-in))
(defn on-load-error
[set-error]
(js/setTimeout set-error error-wait-time))
(defn- loading-image
[{:keys [theme gradient-color-index loader-opacity aspect-ratio]}]
[reanimated/view {:style (style/loading-image-with-opacity loader-opacity)}
[gradients/view
{:theme theme
:container-style (style/gradient-view aspect-ratio)
:color-index gradient-color-index}]])
(defn- counter-view
[counter]
[collectible-counter/view
@@ -21,7 +43,7 @@
(defn- fallback-view
[{:keys [label theme counter on-mount]}]
(rn/use-mount on-mount)
[rn/view {:style (style/fallback {:theme theme})}
[rn/view {:style (style/fallback theme)}
[counter-view counter]
[rn/view
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
@@ -31,56 +53,71 @@
:style {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}}
label]])
(defn- collectible-image
[{:keys [aspect-ratio theme gradient-color-index supported-file? set-error native-ID
square? image-src on-collectible-load counter]}]
(let [loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))]
[:<>
[loading-image
{:aspect-ratio aspect-ratio
:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}]
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style (style/image square? aspect-ratio theme)
:source image-src
:native-ID native-ID
:on-load-end (fn []
(on-load-end {:loader-opacity loader-opacity
:image-opacity image-opacity}))
:on-error #(on-load-error set-error)
:on-load on-collectible-load}]
(when counter
[counter-view counter])
[rn/view {:style (style/collectible-border theme)}]]]))
(defn view-internal
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
on-collectible-load]}]
(let [theme (quo.theme/use-theme)
[image-size set-image-size] (rn/use-state {})
[image-error? set-image-error] (rn/use-state (or (nil? image-src)
(string/blank? image-src)))]
(rn/use-effect
(fn []
(promesa/let [[image-width image-height] (rn/image-get-size image-src)]
(set-image-size {:width image-width
:height image-height
:aspect-ratio (/ image-width image-height)})))
[image-src])
on-collectible-load aspect-ratio gradient-color-index]
:or {gradient-color-index :gradient-1
on-collectible-load (fn [])}}]
(let [theme (quo.theme/use-theme)
[error? set-error] (rn/use-state (or (nil? image-src)
(string/blank? image-src)))]
[rn/pressable
{:on-press (when (and (not image-error?) supported-file?) on-press)
{:style (merge container-style (style/container aspect-ratio))
:accessibility-label :expanded-collectible
:style (merge container-style style/container)}
(cond
(not supported-file?)
:on-press (when (and (not error?) supported-file?)
on-press)}
(if (or (not supported-file?) error?)
[fallback-view
{:label (i18n/label :t/unsupported-file)
{:label (i18n/label (if-not supported-file?
:t/unsupported-file
:t/cant-fetch-info))
:counter counter
:theme theme
:on-mount on-collectible-load}]
image-error?
[fallback-view
{:label (i18n/label :t/cant-fetch-info)
:counter counter
:theme theme
:on-mount on-collectible-load}]
:else
[rn/view
[rn/image
{:style (style/image square? (:aspect-ratio image-size) theme)
:source image-src
:native-ID native-ID
:on-error #(set-image-error true)
:on-load on-collectible-load}]
(when counter
[counter-view counter])
[rn/view {:style (style/collectible-border theme)}]])]))
[collectible-image
{:aspect-ratio aspect-ratio
:theme theme
:supported-file? supported-file?
:set-error set-error
:native-ID native-ID
:square? square?
:image-src image-src
:on-collectible-load on-collectible-load
:counter counter
:gradient-color-index gradient-color-index}])]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:aspect-ratio {:optional true} [:maybe number?]]
[:image-src {:optional true} [:maybe string?]]
[:supported-file? {:optional true} [:maybe boolean?]]
[:container-style {:optional true} [:maybe :map]]
@@ -88,7 +125,8 @@
[:square? {:optional true} [:maybe boolean?]]
[:counter {:optional true} [:maybe string?]]
[:on-press {:optional true} [:maybe fn?]]
[:on-collectible-load {:optional true} [:maybe fn?]]]]]
[:on-collectible-load {:optional true} [:maybe fn?]]
[:gradient-color-index {:optional true} [:maybe keyword?]]]]]
:any])
(def view (schema/instrument #'view-internal ?schema))
@@ -12,7 +12,8 @@
[{:keys [checked? blur? accessibility-label container-style on-change icon customization-color]} label]
(let [theme (quo.theme/use-theme)]
[rn/touchable-without-feedback
{:on-press on-change
{:on-press (when on-change
#(on-change (not checked?)))
:accessibility-label :disclaimer-touchable-opacity}
[rn/view {:style (merge container-style (style/container blur? theme))}
[selectors/view
@@ -6,8 +6,14 @@
[{:keys [size card? blur? actionable? theme]}]
{:flex-direction :row
:justify-content :space-between
:padding-vertical (when (= size :default) 8)
:padding-horizontal (when (= size :default) 12)
:padding-vertical (case size
:default 8
:large 12
nil)
:padding-horizontal (case size
:default 12
:large 16
nil)
:border-radius 16
:border-width (when (and card? (not= size :small)) 1)
:background-color (if blur?
@@ -24,15 +30,27 @@
(defn loading-container
[size blur? theme]
{:width (if (= size :default) 132 72)
:height (if (= size :default) 16 10)
{:width (case size
:large 132
:small 72
132)
:height (case size
:large 16
:small 10
16)
:background-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-5
colors/neutral-90
theme))
:border-radius (if (= size :default) 6 3)
:margin-vertical (if (= size :default) 4 3)})
:border-radius (case size
:large 6
:small 3
6)
:margin-vertical (case size
:large 4
:small 3
4)})
(def subtitle-container
{:flex-direction :row
@@ -6,7 +6,7 @@
[:type {:optional true}
[:maybe
[:enum :default :multiuser :group :channel :community :token :network :multinetwork :account
:collectible :address :icon :audio :wallet-user]]]
:collectible :address :icon :audio :wallet-user :dapp]]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]
[:blur? {:optional true} [:maybe :boolean]]
+90 -83
View File
@@ -17,16 +17,18 @@
[schema.core :as schema]))
(defn- tag-skeleton
[{:keys [size text] :or {size 24}} logo-component]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]]))
[{:keys [size text theme]
:or {size 24
theme (quo.theme/use-theme)}}
logo-component]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]])
(defn- communities-tag
[{:keys [size community-logo community-name blur? channel? channel-name]}]
@@ -81,95 +83,100 @@
context]]]))
(defn- view-internal
[{:keys [type size state blur? customization-color profile-picture full-name users
[{:keys [type theme size state blur? customization-color profile-picture full-name users
group-name amount token network-logo network-name networks
account-name emoji collectible collectible-name collectible-number duration container-style]
account-name emoji collectible collectible-name collectible-number
dapp-name dapp-logo duration container-style]
:or {customization-color :blue
type :default
state :default}
state :default
theme (quo.theme/use-theme)}
:as props}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (merge {:align-items :flex-start} container-style)}
[rn/view
{:style (style/container {:theme theme
:type type
:size size
:state state
:blur? blur?
:customization-color customization-color})
:accessibility-label :context-tag}
(case type
:default
[tag-skeleton {:theme theme :size size :text full-name}
[user-avatar/user-avatar
{:full-name full-name
:profile-picture profile-picture
:size (if (= size 24) :xxs 28)
:status-indicator? false
:ring? false
:customization-color customization-color}]]
[rn/view {:style (merge {:align-items :flex-start} container-style)}
[rn/view
{:style (style/container {:theme theme
:type type
:size size
:state state
:blur? blur?
:customization-color customization-color})
:accessibility-label :context-tag}
(case type
:default
[tag-skeleton {:theme theme :size size :text full-name}
[user-avatar/user-avatar
{:full-name full-name
:profile-picture profile-picture
:size (if (= size 24) :xxs 28)
:status-indicator? false
:ring? false
:customization-color customization-color}]]
:multiuser
[preview-list/view {:type :user :size :size-20}
users]
:multiuser
[preview-list/view {:type :user :size :size-20}
users]
:multinetwork
[preview-list/view {:type :network :size :size-20}
networks]
:multinetwork
[preview-list/view {:type :network :size :size-20}
networks]
:audio
[tag-skeleton {:theme theme :text (str duration)}
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
:audio
[tag-skeleton {:theme theme :text (str duration)}
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
:group
[tag-skeleton {:theme theme :size size :text group-name}
[group-avatar/view
{:icon-name :i/members
:size (if (= size 24) :size-20 :size-28)
:customization-color (colors/custom-color customization-color 50)}]]
:group
[tag-skeleton {:theme theme :size size :text group-name}
[group-avatar/view
{:icon-name :i/members
:size (if (= size 24) :size-20 :size-28)
:customization-color (colors/custom-color customization-color 50)}]]
(:channel :community)
[communities-tag (assoc props :channel? (= type :channel))]
(:channel :community)
[communities-tag (assoc props :channel? (= type :channel))]
:token
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
[token/view
{:style (style/token-logo size)
:token token
:size (if (= size 24) :size-20 :size-28)}]]
:token
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
[token/view
{:style (style/token-logo size)
:token token
:size (if (= size 24) :size-20 :size-28)}]]
:network
[tag-skeleton {:theme theme :size size :text network-name}
[rn/image {:style (style/circle-logo size) :source network-logo}]]
:network
[tag-skeleton {:theme theme :size size :text network-name}
[rn/image {:style (style/circle-logo size) :source network-logo}]]
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:account
[tag-skeleton {:theme theme :size size :text account-name}
[account-avatar/view
{:customization-color customization-color
:emoji emoji
:size (if (= size 24) 20 28)}]]
:account
[tag-skeleton {:theme theme :size size :text account-name}
[account-avatar/view
{:customization-color customization-color
:emoji emoji
:size (if (= size 24) 20 28)}]]
:address
[address-tag props]
:address
[address-tag props]
:icon
[icon-tag props]
:icon
[icon-tag props]
:wallet-user
[tag-skeleton {:theme theme :size size :text full-name}
[wallet-user-avatar/wallet-user-avatar
{:full-name full-name
:size (if (= size 24) :size-20 :size-24)
:customization-color customization-color}]]
:wallet-user
[tag-skeleton {:theme theme :size size :text full-name}
[wallet-user-avatar/wallet-user-avatar
{:full-name full-name
:size (if (= size 24) :size-20 :size-24)
:customization-color customization-color}]]
nil)]]))
:dapp
[tag-skeleton {:theme theme :size size :text dapp-name}
[rn/image {:style (style/circle-logo size) :source dapp-logo}]]
nil)]])
(def view (schema/instrument #'view-internal component-schema/?schema))
+1 -1
View File
@@ -102,7 +102,7 @@
:container-style container-style
:theme theme))
:on-press #(when (= action :selector) (on-press))
:pointer-events :box-only}
:pointer-events (when (= action :selector) :box-only)}
[rn/view {:style style/header-container}
[avatar props]
[rn/view
+2 -2
View File
@@ -68,7 +68,7 @@
quo.components.graph.wallet-graph.view
quo.components.header
quo.components.icon
quo.components.info.info-message
quo.components.info.info-message.view
quo.components.info.information-box.view
quo.components.inputs.address-input.view
quo.components.inputs.input.view
@@ -301,7 +301,7 @@
(def icon quo.components.icon/icon)
;;;; Info
(def info-message quo.components.info.info-message/info-message)
(def info-message quo.components.info.info-message.view/view)
(def information-box quo.components.info.information-box.view/view)
;;;; Inputs
+1
View File
@@ -41,6 +41,7 @@
quo.components.dropdowns.network-dropdown.component-spec
quo.components.gradient.gradient-cover.component-spec
quo.components.graph.wallet-graph.component-spec
quo.components.info.info-message.component-spec
quo.components.inputs.address-input.component-spec
quo.components.inputs.input.component-spec
quo.components.inputs.locked-input.component-spec
+7 -6
View File
@@ -24,12 +24,13 @@
(get ui k))
(def dapps
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
:1inch (js/require "../resources/images/dapps/1inch.png")
:aave (js/require "../resources/images/dapps/Aave.png")
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
:zapper (js/require "../resources/images/dapps/Zapper.png")
:zerion (js/require "../resources/images/dapps/Zerion.png")})
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
:1inch (js/require "../resources/images/dapps/1inch.png")
:aave (js/require "../resources/images/dapps/Aave.png")
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
:zapper (js/require "../resources/images/dapps/Zapper.png")
:zerion (js/require "../resources/images/dapps/Zerion.png")
:wallet-connect (js/require "../resources/images/dapps/WalletConnect.png")})
(defn get-dapp
[k]
@@ -0,0 +1,24 @@
(ns status-im.common.check-before-syncing.style)
(def buttons-container
{:flex-direction :row
:justify-content :space-between
:gap 12
:padding-vertical 12})
(def button {:flex 1})
(def checkbox
{:margin-top 16
:flex-direction :row
:align-items :center})
(def checkbox-text {:margin-left 10})
(def checkboxes-container {:margin-bottom 10 :padding-right 10})
(def header {:margin-bottom 8})
(def description {:margin-right -33})
(def view-container {:padding-horizontal 33})
@@ -0,0 +1,74 @@
(ns status-im.common.check-before-syncing.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.check-before-syncing.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def checks
[(i18n/label :t/check-before-syncing-doc-checkbox-1)
(i18n/label :t/check-before-syncing-doc-checkbox-2)
(i18n/label :t/check-before-syncing-doc-checkbox-3)])
(defn- checkbox
[on-change customization-color description]
[rn/view {:style style/checkbox}
[quo/selectors
{:type :checkbox
:blur? true
:customization-color customization-color
:on-change on-change}]
[quo/text {:style style/checkbox-text} description]])
(defn- compute-new-checked-count
[set-checked-count checked?]
(if checked?
(set-checked-count inc)
(set-checked-count dec)))
(defn- hide-bottom-sheet
[]
(rf/dispatch [:hide-bottom-sheet]))
(defn view
[{:keys [on-submit customization-color]}]
(let [[checked-count set-checked-count] (rn/use-state 0)
on-change (partial compute-new-checked-count set-checked-count)
render-checkbox (rn/use-callback
(partial checkbox on-change customization-color)
[customization-color])
on-cancel hide-bottom-sheet
on-continue (rn/use-callback
(fn []
(hide-bottom-sheet)
(on-submit))
[on-submit])]
[rn/view
{:style style/view-container
:accessibility-label :check-before-syncing-bottom-sheet}
[quo/text
{:weight :semi-bold
:size :heading-2
:style style/header} (i18n/label :t/check-before-syncing)]
[quo/text {:style style/description} (i18n/label :t/check-before-syncing-doc-description)]
(into
[rn/view {:style style/checkboxes-container}]
(mapv render-checkbox checks))
[rn/view {:style style/buttons-container}
[quo/button
{:type :grey
:container-style style/button
:accessibility-label :cancel-button
:on-press on-cancel}
(i18n/label :t/cancel)]
[quo/button
{:container-style style/button
:disabled? (not= checked-count (count checks))
:customization-color (or customization-color :blue)
:accessibility-label :continue-button
:on-press on-continue}
(i18n/label :t/continue)]]]))
@@ -6,7 +6,8 @@
(defn contact-list-item
[{:keys [on-press on-long-press accessory allow-multiple-presses? disabled?]}
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?
container-style]}
theme]
(let [photo-path (rf/sub [:chats/photo-path public-key])
online? (rf/sub [:visibility-status-updates/online? public-key])
@@ -25,4 +26,5 @@
:on-press on-press
:on-long-press on-long-press
:accessory accessory
:container-style container-style
:disabled? disabled?}]))
@@ -1,6 +1,7 @@
(ns status-im.common.floating-button-page.floating-container.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.floating-container.style :as style]))
@@ -9,9 +10,10 @@
[child]
(let [theme (quo.theme/use-theme)]
[quo/blur
{:blur-amount 12
:blur-radius 12
:blur-type theme}
{:blur-amount 52
:blur-radius 20
:blur-type :transparent
:blur-overlay-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme)}
[rn/view {:style style/blur-inner-container}
child]]))
@@ -31,10 +31,10 @@
:on-change-text #(reset! entered-password %)}]
(when (not-empty error)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:containstyle {:margin-top 8}}
{:status :error
:size :default
:icon :i/info
:container-style {:margin-top 8}}
(i18n/label :t/oops-wrong-password)])
[quo/button
{:container-style {:margin-bottom 12 :margin-top 40}
@@ -0,0 +1,17 @@
(ns status-im.common.peer-stats.events
(:require
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/reg-event-fx :peer-stats/get-count
(fn []
{:fx [[:json-rpc/call
[{:method :wakuext_peers
:on-success [:peer-stats/get-count-success]
:on-error (fn [error]
(log/error "failed to fetch wakuv2 peer count"
{:error error}))}]]]}))
(rf/reg-event-fx :peer-stats/get-count-success
(fn [{:keys [db]} [response]]
{:db (assoc db :peer-stats/count (count response))}))
+2 -4
View File
@@ -195,7 +195,7 @@
true)
(defn view
[{:keys [title subtitle validate-fn on-success-scan error-message share-button? import-keypair?]}]
[{:keys [title subtitle validate-fn on-success-scan error-message share-button?]}]
(let [insets (safe-area/get-insets)
qr-code-succeed? (reagent/atom false)
qr-view-finder (reagent/atom {})
@@ -233,9 +233,7 @@
:set-qr-code-succeeded (fn [value]
(when on-success-scan
(on-success-scan value))
(if import-keypair?
(set-rescan-timeout)
(rf/dispatch [:navigate-back])))
(rf/dispatch [:navigate-back]))
:set-rescan-timeout set-rescan-timeout}])
[rn/view {:style (style/root-container (:top insets))}
[header
+2 -13
View File
@@ -10,7 +10,6 @@
[status-im.contexts.communities.discover.events]
[status-im.contexts.profile.push-notifications.local.events :as local-notifications]
[taoensso.timbre :as log]
[utils.debounce :as debounce]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
@@ -20,17 +19,10 @@
peers-count (count peers-summary)]
(rf/merge cofx
{:db (assoc db
:peers-summary peers-summary
:peers-count peers-count)}
:peers-summary peers-summary
:peer-stats/count peers-count)}
(visibility-status-updates/peers-summary-change peers-count))))
(rf/reg-event-fx :wakuv2-peer-stats
(fn [{:keys [db]} [^js peer-stats-js]]
(let [peer-stats (transforms/js->clj peer-stats-js)]
{:db (assoc db
:peer-stats peer-stats
:peers-count (count (:peers peer-stats)))})))
(rf/defn process
{:events [:signals/signal-received]}
[{:keys [db] :as cofx} event-str]
@@ -46,9 +38,6 @@
"wallet"
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
"wakuv2.peerstats"
(debounce/debounce-and-dispatch [:wakuv2-peer-stats event-js] 1000)
"envelope.sent"
(messages.transport/update-envelopes-status
cofx
@@ -32,9 +32,8 @@
:on-cancel #(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
:on-success (fn []
(when (fn? on-close)
(on-close))
(rf/dispatch [:standard-auth/on-biometric-success on-auth-success]))
(rf/dispatch [:standard-auth/on-biometric-success on-auth-success])
(rf/dispatch [:standard-auth/close on-close]))
:on-fail (fn [err]
(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
@@ -48,6 +47,7 @@
[{:keys [db]} [on-auth-success]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:keychain/get-user-password [key-uid on-auth-success]]
[:dispatch [:standard-auth/set-success true]]
[:dispatch [:standard-auth/reset-login-password]]]}))
(schema/=> on-biometric-success events-schema/?on-biometric-success)
@@ -74,6 +74,7 @@
(fn [password]
(let [sha3-pwd (security/hash-masked-password password)
on-auth-success-callback #(on-auth-success sha3-pwd)]
(rf/dispatch [:standard-auth/set-success true])
(rf/dispatch [:standard-auth/reset-login-password])
(if has-partially-operable-accounts?
(rf/dispatch [:wallet/make-partially-operable-accounts-fully-operable
@@ -92,10 +93,7 @@
{:fx [[:dispatch [:standard-auth/reset-login-password]]
[:dispatch
[:show-bottom-sheet
{:on-close (fn []
(rf/dispatch [:standard-auth/reset-login-password])
(when on-close
(on-close)))
{:on-close #(rf/dispatch [:standard-auth/close on-close])
:theme theme
:shell? blur?
:content #(bottom-sheet-password-view args)}]]]})
@@ -107,3 +105,23 @@
:standard-auth/reset-login-password
(fn [{:keys [db]}]
{:db (update db :profile/login dissoc :password :error)}))
(rf/reg-fx
:standard-auth/on-close
(fn [{:keys [on-close success?]}]
(when on-close
(on-close success?))))
(rf/reg-event-fx
:standard-auth/close
(fn [{:keys [db]} [on-close]]
{:db (assoc-in db [:profile/login :success?] false)
:fx [[:dispatch [:standard-auth/reset-login-password]]
[:standard-auth/on-close
{:on-close on-close
:success? (get-in db [:profile/login :success?])}]]}))
(rf/reg-event-fx
:standard-auth/set-success
(fn [{:keys [db]} [success?]]
{:db (assoc-in db [:profile/login :success?] success?)}))
@@ -16,8 +16,7 @@
[error]
(if (and (some? error)
(or (= error "file is not a database")
(string/starts-with? error "failed to set ")
(string/starts-with? error "Failed")))
(string/starts-with? (string/lower-case error) "failed")))
(i18n/label :t/oops-wrong-password)
error))
@@ -34,9 +33,9 @@
[theme])]
[rn/view {:style style/error-message}
[quo/info-message
{:type :error
:size :default
:icon :i/info}
{:status :error
:size :default
:icon :i/info}
error-message]
[rn/pressable
{:hit-slop {:top 6 :bottom 20 :left 0 :right 0}
@@ -16,7 +16,8 @@
on-complete (rn/use-callback
(fn [reset]
(rf/dispatch [:standard-auth/authorize
{:on-close #(js/setTimeout reset 200)
{:on-close (fn [success?]
(js/setTimeout #(reset success?) 200))
:auth-button-icon-left auth-button-icon-left
:theme theme
:blur? blur?
+12
View File
@@ -282,6 +282,8 @@
(def ^:const wallet-connect-session-proposal-event "session_proposal")
(def ^:const wallet-connect-session-request-event "session_request")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
(def ^:const dapp-permission-qr-code "qr-code")
@@ -503,6 +505,9 @@
(def ^:const optimism-network-name :optimism)
(def ^:const arbitrum-network-name :arbitrum)
(def ^:const layer-1-network 1)
(def ^:const layer-2-network 2)
(def ^:const default-network-names [mainnet-network-name optimism-network-name arbitrum-network-name])
(def ^:const default-network-count (count default-network-names))
@@ -548,3 +553,10 @@
(def ^:const community-joined-notification-type "communityJoined")
(def ^:const default-telemetry-server-url "https://telemetry.status.im")
(def ^:const contact-item-height 56)
(def ^:const slippages [0.1 0.5 1])
(def ^:const default-slippage 0.5)
(def ^:const max-recommended-slippage 5)
(def ^:const max-slippage-decimal-places 2)
@@ -105,10 +105,10 @@
:max-length constants/max-group-chat-name-length}]
(when error-message
[quo/info-message
{:type :error
:icon :i/info
:size :default
:style {:margin-top 8 :margin-left 20 :margin-bottom 16}}
{:status :error
:icon :i/info
:size :default
:container-style {:margin-top 8 :margin-left 20 :margin-bottom 16}}
error-message])
[quo/divider-line]
[rn/view
@@ -173,20 +173,21 @@
(defn avatar-view
[{:keys [contact chat-id full-name color muted? image]}]
(if contact ; `contact` is passed when it's not a group chat
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])
photo-path (rf/sub [:chats/photo-path chat-id])]
[quo/user-avatar
(cond-> {:full-name full-name
:size :small
:online? online?
:profile-picture photo-path}
muted?
(assoc :ring? false))])
[quo/group-avatar
{:customization-color color
:picture (when image {:uri image})
:size :size-32}]))
[rn/view {:style {:justify-content :center}}
(if contact ; `contact` is passed when it's not a group chat
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])
photo-path (rf/sub [:chats/photo-path chat-id])]
[quo/user-avatar
(cond-> {:full-name full-name
:size :small
:online? online?
:profile-picture photo-path}
muted?
(assoc :ring? false))])
[quo/group-avatar
{:customization-color color
:picture (when image {:uri image})
:size :size-32}])])
(defn- notification-layout
[child]
+2 -1
View File
@@ -66,7 +66,8 @@
(chat-list-item/chat-list-item item theme))
:scroll-event-throttle 8
:content-container-style {:padding-bottom
jump-to.constants/floating-shell-button-height}
jump-to.constants/floating-shell-button-height
:padding-top 8}
:on-scroll #(common.banner/set-scroll-shared-value
{:scroll-input (oops/oget % "nativeEvent.contentOffset.y")
:shared-value scroll-shared-value})}])))
@@ -98,9 +98,8 @@
window-height
loading-indicator-page-loading-height)]
[rn/view {:padding-top top-spacing}
;; Only use animated loading skeleton for ios
;; https://github.com/status-im/status-mobile/issues/17426
[quo/skeleton-list (skeleton-list-props :messages parent-height platform/ios?)]]))
;; Don't use animated loading skeleton https://github.com/status-im/status-mobile/issues/17426
[quo/skeleton-list (skeleton-list-props :messages parent-height false)]]))
(defn header-height
[{:keys [insets able-to-send-message? images reply edit link-previews? input-content-height]}]
@@ -21,6 +21,7 @@
[status-im.contexts.chat.messenger.messages.pin.events :as messages.pin]
[status-im.contexts.communities.events :as communities]
[status-im.contexts.shell.activity-center.events :as activity-center]
[status-im.contexts.wallet.data-store :as wallet.data-store]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
@@ -54,8 +55,11 @@
^js cleared-histories (.-clearedHistories response-js)
^js identity-images (.-identityImages response-js)
^js accounts (.-accounts response-js)
^js keypairs (.-keypairs response-js)
^js ens-username-details-js (.-ensUsernameDetails response-js)
^js customization-color-js (.-customizationColor response-js)
^js saved-addresses-js (.-savedAddresses response-js)
^js watch-only-accounts (.-watchOnlyAccounts response-js)
sync-handler (when-not process-async process-response)]
(cond
@@ -177,6 +181,22 @@
(rf/merge cofx
(process-next response-js sync-handler)))
(seq watch-only-accounts)
(do
(js-delete response-js "watchOnlyAccounts")
(rf/merge cofx
{:fx [[:dispatch
[:wallet/reconcile-watch-only-accounts
(types/js->clj watch-only-accounts)]]]}
(process-next response-js sync-handler)))
(seq keypairs)
(do
(js-delete response-js "keypairs")
(rf/merge cofx
{:fx [[:dispatch [:wallet/reconcile-keypairs (types/js->clj keypairs)]]]}
(process-next response-js sync-handler)))
(seq settings)
(do
(js-delete response-js "settings")
@@ -199,6 +219,13 @@
(models.visibility-status-updates/sync-visibility-status-update
current-visibility-status-clj)))
(seq saved-addresses-js)
(let [saved-addresses (-> saved-addresses-js types/js->clj wallet.data-store/rpc->saved-addresses)]
(js-delete response-js "savedAddresses")
(rf/merge cofx
{:fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]}
(process-next response-js sync-handler)))
(seq ens-username-details-js)
(let [ens-username-details-clj (types/js->clj ens-username-details-js)]
(js-delete response-js "ensUsernameDetails")
@@ -6,32 +6,44 @@
[status-im.common.contact-list-item.view :as contact-list-item]
[status-im.common.contact-list.view :as contact-list]
[status-im.common.home.actions.view :as home.actions]
[status-im.constants :as constants]
[status-im.contexts.communities.actions.channel-view-details.style :as style]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- contact-item
[public-key]
(let [show-profile-actions #(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [home.actions/contact-actions
{:public-key public-key}])}])
[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity
public-key])
{:keys [ens-verified added? compressed-key]} (rf/sub [:contacts/contact-by-address public-key])
theme (quo.theme/use-theme)]
[public-key _ _ {:keys [theme]}]
(let [show-profile-actions (rn/use-callback
(fn []
(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [home.actions/contact-actions
{:public-key public-key}])}]))
[public-key])
on-press (rn/use-callback
(fn []
(rf/dispatch [:chat.ui/show-profile public-key]))
[public-key])
[primary-name
secondary-name] (rf/sub [:contacts/contact-two-names-by-identity public-key])
{:keys [ens-verified
added?
compressed-key]} (rf/sub [:contacts/contact-by-address public-key])]
[contact-list-item/contact-list-item
{:on-press #(rf/dispatch [:chat.ui/show-profile public-key])
{:on-press on-press
:on-long-press show-profile-actions
:accessory {:type :options
:on-press show-profile-actions}}
{:primary-name primary-name
:secondary-name secondary-name
:compressed-key compressed-key
:public-key public-key
:ens-verified ens-verified
:added? added?}
{:primary-name primary-name
:secondary-name secondary-name
:compressed-key compressed-key
:public-key public-key
:ens-verified ens-verified
:added? added?
;; We hardcode the height of the container to match exactly the height
;; used in the `get-item-layout` function.
:container-style {:height constants/contact-item-height}}
theme]))
(defn- footer
@@ -40,10 +52,12 @@
(defn- get-item-layout
[_ index]
#js {:length 200 :offset (* 200 index) :index index})
#js {:length constants/contact-item-height
:offset (* constants/contact-item-height index)
:index index})
(defn- members
[items]
[items theme]
[rn/section-list
{:key-fn :public-key
:content-container-style {:padding-bottom 20}
@@ -53,70 +67,70 @@
:sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn footer
:render-data {:theme theme}
:render-fn contact-item
:scroll-event-throttle 8}])
:scroll-event-throttle 32}])
(defn view
[_args]
(fn []
(let [{:keys [chat-id community-id]} (rf/sub [:get-screen-params
:screen/chat.view-channel-members-and-details])
{:keys [description chat-name emoji muted chat-type color]
: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 chat-id])
theme (quo.theme/use-theme)]
(rn/use-mount (fn []
(rf/dispatch [:pin-message/load-pin-messages chat-id])))
[:<>
(when (ff/enabled? ::ff/shell.jump-to)
[quo/floating-shell-button
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:customization-color color
:label (i18n/label :t/jump-to)}}
style/floating-shell-button])
[quo/gradient-cover {:customization-color color :opacity 0.4}]
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/options
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [home.actions/chat-actions
chat
false
true])}])}]}]
[quo/text-combinations
{:container-style style/text-combinations
:title [quo/channel-name
{:channel-name chat-name
:unlocked? true}]
:theme theme
:emoji (when (not (string/blank? emoji)) (string/trim emoji))
:customization-color color
:title-accessibility-label :welcome-title
:description description
:description-accessibility-label :welcome-sub-title}]
[rn/view {:style style/wrapper}
[rn/view
{:style style/channel-actions-wrapper}
[quo/channel-actions
{:actions
[{:big? true
:label (i18n/label :t/pinned-messages-2)
:customization-color color
:icon :i/pin
:counter-value pins-count
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet
chat-id]))}
{:label (if muted (i18n/label :t/unmute-channel) (i18n/label :t/mute-channel))
:customization-color color
:icon (if muted :i/muted :i/activity-center)
:on-press (fn []
(if muted
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id chat-type muted)))}]}]]]
[members items color]])))
[]
(let [{:keys [chat-id community-id]} (rf/sub [:get-screen-params
:screen/chat.view-channel-members-and-details])
{:keys [description chat-name emoji muted chat-type color]
: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 chat-id])
theme (quo.theme/use-theme)]
(rn/use-mount (fn []
(rf/dispatch [:pin-message/load-pin-messages chat-id])))
[:<>
(when (ff/enabled? ::ff/shell.jump-to)
[quo/floating-shell-button
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:customization-color color
:label (i18n/label :t/jump-to)}}
style/floating-shell-button])
[quo/gradient-cover {:customization-color color :opacity 0.4}]
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/options
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [home.actions/chat-actions
chat
false
true])}])}]}]
[quo/text-combinations
{:container-style style/text-combinations
:title [quo/channel-name
{:channel-name chat-name
:unlocked? true}]
:theme theme
:emoji (when (not (string/blank? emoji)) (string/trim emoji))
:customization-color color
:title-accessibility-label :welcome-title
:description description
:description-accessibility-label :welcome-sub-title}]
[rn/view {:style style/wrapper}
[rn/view
{:style style/channel-actions-wrapper}
[quo/channel-actions
{:actions
[{:big? true
:label (i18n/label :t/pinned-messages-2)
:customization-color color
:icon :i/pin
:counter-value pins-count
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet
chat-id]))}
{:label (if muted (i18n/label :t/unmute-channel) (i18n/label :t/mute-channel))
:customization-color color
:icon (if muted :i/muted :i/activity-center)
:on-press (fn []
(if muted
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id chat-type muted)))}]}]]]
[members items theme]]))
@@ -4,6 +4,7 @@
re-frame.db
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
@@ -25,6 +26,14 @@
[:onboarding/navigate-to-sign-in-by-syncing]
1000))
(defn- show-check-before-syncing
[]
(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [check-before-syncing/view
{:on-submit navigate-to-sign-in-by-syncing}])
:shell? true}]))
(defn- navigate-to-sign-in-by-seed-phrase
[create-profile?]
(rf/dispatch [:onboarding/navigate-to-sign-in-by-seed-phrase
@@ -62,7 +71,7 @@
: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}])
:on-press show-check-before-syncing}])
(defn sign-in-options
[sign-in-type]
@@ -38,14 +38,11 @@
[rn/view {:style style/info-message}
(when shown
[quo/info-message
{:type status
:size :default
:icon (if (= status :success) :i/positive-state :i/info)
:text-color (when (= status :default)
colors/white-70-blur)
:icon-color (when (= status :default)
colors/white-70-blur)
:style {}}
{:status status
:size :default
:icon (if (= status :success) :i/positive-state :i/info)
:color (when (= status :default)
colors/white-70-blur)}
text])]])
(defn password-inputs
@@ -158,12 +158,11 @@
:on-change-text on-change-text}}]]
[quo/info-message
{:type info-type
:size :default
:icon (if valid-name? :i/positive-state :i/info)
:text-color (when (= :default info-type) colors/white-70-blur)
:icon-color (when (= :default info-type) colors/white-70-blur)
:style style/info-message}
{:status info-type
:size :default
:icon (if valid-name? :i/positive-state :i/info)
:color (when (= :default info-type) colors/white-70-blur)
:container-style style/info-message}
info-message]
[quo/text
{:size :paragraph-2
@@ -1,7 +1,6 @@
(ns status-im.contexts.preview.quo.buttons.slide-button
(:require
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.contexts.preview.quo.preview :as preview]))
@@ -18,41 +17,36 @@
:type :boolean}
{:key :blur?
:type :boolean}
{:key :keep-at-end-after-slide?
:type :boolean}
(preview/customization-color-option {:key :color})])
(defn f-view
[]
(let [state (reagent/atom {:disabled? false
:color :blue
:size :size-48})
color (reagent/cursor state [:color])
blur? (reagent/cursor state [:blur?])
complete? (reagent/atom false)]
(let [state (reagent/atom {:disabled? false
:color :blue
:size :size-48
:keep-at-end-after-slide? false})
color (reagent/cursor state [:color])
blur? (reagent/cursor state [:blur?])
keep-at-end-after-slide? (reagent/cursor state [:keep-at-end-after-slide?])]
(fn []
(rn/use-effect (fn []
(reset! complete? true)
(js/setTimeout #(reset! complete? false) 50))
[(:size @state)])
[preview/preview-container
{:state state
:descriptor descriptor
:component-container-style (when-not @blur? (:align-items :center))
:blur? @blur?
:show-blur-background? true}
(if (not @complete?)
[quo/slide-button
{:track-text "We gotta slide"
:track-icon :face-id
:customization-color @color
:size (:size @state)
:disabled? (:disabled? @state)
:blur? @blur?
:type (:type @state)
:on-complete (fn [_]
(js/setTimeout (fn [] (reset! complete? true))
1000)
(js/alert "I don't wanna slide anymore"))}]
[quo/button {:on-press (fn [] (reset! complete? false))}
"Try again"])])))
[quo/slide-button
{:track-text "We gotta slide"
:track-icon :face-id
:customization-color @color
:size (:size @state)
:disabled? (:disabled? @state)
:blur? @blur?
:type (:type @state)
:on-complete (fn [reset-fn]
(js/alert "Slide complete")
(reset-fn @keep-at-end-after-slide?))}]])))
(defn view [] [:f> f-view])
@@ -1,28 +1,43 @@
(ns status-im.contexts.preview.quo.info.info-message
(:require
[quo.core :as quo]
[reagent.core :as reagent]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:key :type
[{:key :status
:type :select
:options [{:key :default}
{:key :success}
{:key :error}]}
{:key :error}
{:key :warning}]}
{:key :size
:type :select
:options [{:key :default}
{:key :tiny}]}
{:key :blur?
:type :boolean}
{:key :icon
:type :select
:options [{:key :i/placeholder}
{:key :i/info}]}
{:key :message
:type :text}])
(defn view
[]
(let [state (reagent/atom {:type :default
:size :default
:icon :i/placeholder
:message "This is a message"})]
(fn []
[preview/preview-container {:state state :descriptor descriptor}
[quo/info-message @state (:message @state)]])))
(let [[state set-state] (rn/use-state
{:status :default
:size :default
:message "This is a message"
:blur? false
:icon :i/placeholder})
blur? (:blur? state)]
[preview/preview-container
{:state state
:descriptor descriptor
:blur-dark-only? true
:show-blur-background? blur?
:blur? blur?
:set-state set-state}
[quo/info-message (dissoc state :message) (:message state)]]))
@@ -65,9 +65,9 @@
:customization-color :blue}
:header [rn/view
[quo/info-message
{:type :success
:size :tiny
:icon :i/placeholder}
{:status :success
:size :tiny
:icon :i/placeholder}
"info-message as title"]]
:body [quo/snippet {:language :clojure :max-lines 15 :syntax true}
snippet-preview/clojure-example]
@@ -55,7 +55,8 @@
{:type :select
:key :size
:options [{:key :default}
{:key :small}]}])
{:key :small}
{:key :large}]}])
(defn view
[]
+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?})))
@@ -68,9 +68,9 @@
:on-change-text on-nickname-change
:on-submit-editing on-nickname-submit}]
[quo/info-message
{:icon :i/info
:size :default
:type (if-not (string/blank? error-msg) :error :default)}
{:icon :i/info
:size :default
:status (if-not (string/blank? error-msg) :error :default)}
(if-not (string/blank? error-msg)
error-msg
(i18n/label :t/nickname-visible-to-you))]]
@@ -58,9 +58,9 @@
:on-change-text on-change-text}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info}
{:status :error
:size :default
:icon :i/info}
error-msg])]
[rn/view {:style style/button-wrapper}
[quo/button
@@ -58,9 +58,9 @@
:on-change-text on-change-text}]
(when-not (string/blank? @error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info}
{:status :error
:size :default
:icon :i/info}
@error-msg])]
[rn/view {:style style/button-wrapper}
[quo/button
@@ -83,8 +83,7 @@
[[:profile.settings/switch-theme-fx
[(or (:appearance settings)
constants/theme-type-dark)
:shell-stack
false]]
:shell-stack]]
[:dispatch [:init-root :shell-stack]]
[:dispatch [:profile/show-testnet-mode-banner-if-enabled]]]))})))
@@ -5,6 +5,7 @@
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.confirmation-drawer.view :as confirmation-drawer]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.config :as config]
@@ -41,6 +42,17 @@
:linear
50))
(defn- show-check-before-syncing
[]
(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [check-before-syncing/view
{:on-submit
#(debounce/throttle-and-dispatch
[:open-modal :screen/onboarding.sign-in]
1000)}])
:shell? true}]))
(defn new-account-options
[]
[quo/action-drawer
@@ -55,9 +67,7 @@
:accessibility-label :create-new-profile}
{:icon :i/multi-profile
:label (i18n/label :t/add-existing-status-profile)
:on-press #(debounce/throttle-and-dispatch
[:open-modal :screen/onboarding.sign-in]
1000)
:on-press show-check-before-syncing
:accessibility-label :multi-profile}]]])
(defn show-new-account-options
@@ -4,7 +4,6 @@
[react-native.platform :as platform]
[status-im.common.theme.core :as theme]
[status-im.constants :as constants]
[status-im.setup.hot-reload :as hot-reload]
[utils.re-frame :as rf]))
(re-frame/reg-fx
@@ -20,7 +19,7 @@
(re-frame/reg-fx
:profile.settings/switch-theme-fx
(fn [[theme-type view-id reload-ui?]]
(fn [[theme-type view-id]]
(let [theme (if (or (= theme-type constants/theme-type-dark)
(and (= theme-type constants/theme-type-system)
(theme/device-theme-dark?)))
@@ -28,8 +27,4 @@
:light)]
(theme/set-legacy-theme theme)
(rf/dispatch [:theme/switch theme])
(rf/dispatch [:reload-status-nav-color view-id])
(when reload-ui?
(re-frame/dispatch [:dismiss-all-overlays])
(when js/goog.DEBUG
(hot-reload/reload))))))
(rf/dispatch [:reload-status-nav-color view-id]))))
@@ -95,14 +95,14 @@
(rf/reg-event-fx :profile.settings/change-appearance
(fn [_ [theme]]
{:fx [[:dispatch [:profile.settings/profile-update :appearance theme]]
[:profile.settings/switch-theme-fx [theme :appearance true]]]}))
[:profile.settings/switch-theme-fx [theme :appearance]]]}))
(rf/reg-event-fx :profile.settings/switch-theme
(fn [{:keys [db]} [theme view-id]]
(let [theme (or theme
(get-in db [:profile/profile :appearance])
constants/theme-type-dark)]
{:fx [[:profile.settings/switch-theme-fx [theme view-id false]]]})))
{:fx [[:profile.settings/switch-theme-fx [theme view-id]]]})))
(rf/reg-fx :profile.settings/get-profile-picture
(fn [key-uid]
@@ -61,7 +61,14 @@
:image :icon
:blur? true
:action :arrow})]
[{:title (i18n/label :t/syncing)
[(when config/show-not-implemented-features?
{:title (i18n/label :t/privacy-and-security)
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
:image-props :i/privacy
:image :icon
:blur? true
:action :arrow})
{:title (i18n/label :t/syncing)
:on-press #(rf/dispatch [:open-modal :settings-syncing])
:image-props :i/syncing
:image :icon
@@ -24,12 +24,11 @@
[rn/view {:style style/info-message}
(when shown?
[quo/info-message
(cond-> {:type status
:size :default}
(cond-> {:status status
:size :default}
(not= :success status) (assoc :icon :i/info)
(= :success status) (assoc :icon :i/positive-state)
(= :default status) (assoc :text-color colors/white-70-blur
:icon-color colors/white-70-blur))
(= :default status) (assoc :color colors/white-70-blur))
text])]])
(defn- calc-password-strength
@@ -43,9 +43,9 @@
{:style style/error-container}
(when error
[quo/info-message
{:type :error
:size :default
:icon :i/info}
{:status :error
:size :default
:icon :i/info}
(i18n/label :t/oops-wrong-password)])]
[quo/information-box
{:type :error
@@ -1,5 +1,6 @@
(ns status-im.contexts.profile.settings.visibility-sheet.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -17,6 +18,10 @@
[:visibility-status-updates/visibility-status-update
public-key])
customization-color (rf/sub [:profile/customization-color])]
(rn/use-mount
(fn []
(rf/dispatch [:peer-stats/get-count])))
[quo/action-drawer
[[{:icon :i/online
:no-icon-color? true
@@ -0,0 +1,11 @@
(ns status-im.contexts.settings.privacy-and-security.style)
(def title-container
{:flex 0
:padding-horizontal 20
:margin-vertical 12})
(defn page-wrapper
[top-inset]
{:padding-top top-inset
:flex 1})
@@ -0,0 +1,42 @@
(ns status-im.contexts.settings.privacy-and-security.view
(:require
[quo.core :as quo]
[quo.theme]
[react-native.safe-area :as safe-area]
[status-im.contexts.settings.privacy-and-security.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn view
[]
(let [insets (safe-area/get-insets)
customization-color (rf/sub [:profile/customization-color])]
[quo/overlay
{:type :shell
:container-style (style/page-wrapper (:top insets))}
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back}]
[quo/standard-title
{:title (i18n/label :t/privacy-and-security)
:container-style style/title-container
:accessibility-label :privacy-and-security-header
:customization-color customization-color}]
[quo/category
{:key :category
:data [{:title "Dummy"
:image-props :i/placeholder
:image :icon
:blur? true
:action :selector
:action-props {:on-change identity
:checked? false}
:on-press identity}]
:blur? true
:list-type :settings}]]))
@@ -92,7 +92,7 @@
(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 on-success]}]]
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string]}]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid key-uid
@@ -100,7 +100,6 @@
:keypairs-key-uids keypairs-key-uids
:connection-string connection-string
: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"
@@ -113,7 +112,7 @@
(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 on-import-success]]
[_ [connection-string keypairs-key-uids]]
{:fx [[:dispatch
[:standard-auth/authorize-with-password
{:blur? true
@@ -125,8 +124,7 @@
[:wallet/connection-string-for-import-keypair
{:connection-string connection-string
:keypairs-key-uids keypairs-key-uids
:sha3-pwd password
:on-success on-import-success}]))}]]]})
:sha3-pwd password}]))}]]]})
(rf/reg-event-fx :wallet/success-keypair-qr-scan success-keypair-qr-scan)
@@ -128,9 +128,9 @@
:default-value private-key}]
(when flow-state
[quo/info-message
{:type (if (= flow-state :correct-private-key) :success :error)
:size :default
:icon :i/info}
{:status (if (= flow-state :correct-private-key) :success :error)
:size :default
:icon :i/info}
(case flow-state
:correct-private-key (i18n/label :t/correct-private-key)
:invalid-private-key (i18n/label :t/invalid-private-key)
@@ -13,14 +13,12 @@
on-success-scan (rn/use-callback (fn [scanned-text]
(rf/dispatch [:wallet/success-keypair-qr-scan
scanned-text
keypairs-key-uids
[:navigate-back]])
keypairs-key-uids])
[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-key-pair-qr)
:on-success-scan on-success-scan}]))
@@ -94,9 +94,8 @@
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
{:status :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]]))
@@ -36,8 +36,10 @@
(defn- address-input
[{:keys [input-value on-change-text paste-into-input clear-input]}]
(let [empty-input? (string/blank? input-value)
on-scan-address (rn/use-callback #(rf/dispatch [:open-modal :screen/wallet.scan-address
{:on-result on-change-text}]))]
on-scan-address (rn/use-callback (fn []
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:open-modal :screen/wallet.scan-address
{:on-result on-change-text}])))]
[rn/view {:style style/input-container}
[quo/input
{:accessibility-label :add-address-to-save
@@ -85,8 +87,8 @@
{:accessibility-label :error-message
:size :default
:icon :i/alert
:type :error
:style style/info-message}
:status :error
:container-style style/info-message}
error-msg])))
(defn- existing-saved-address
@@ -161,7 +163,9 @@
(rf/dispatch
[:open-modal :screen/settings.save-address]))
[address ens-name? address-or-ens])]
(rn/use-unmount #(rf/dispatch [:wallet/clear-address-to-save]))
(rn/use-mount (fn []
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clear-address-to-save])))
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
@@ -23,15 +23,29 @@
(rf/reg-event-fx :wallet/save-address save-address)
(defn- update-saved-addresses
[saved-addresses-db new-saved-addresses]
(reduce
(fn [acc {:keys [address removed? test?] :as saved-address}]
(let [db-key (if test? :test :prod)]
(if removed?
(update acc db-key dissoc address)
(assoc-in acc [db-key address] saved-address))))
(or saved-addresses-db
{:test {}
:prod {}})
new-saved-addresses))
(defn reconcile-saved-addresses
[{:keys [db]} [saved-addresses]]
{:db (update-in db [:wallet :saved-addresses] update-saved-addresses saved-addresses)})
(rf/reg-event-fx :wallet/reconcile-saved-addresses reconcile-saved-addresses)
(defn get-saved-addresses-success
[{:keys [db]} [raw-saved-addresses]]
(let [saved-addresses (reduce
(fn [result {:keys [address test?] :as saved-address}]
(assoc-in result [(if test? :test :prod) address] saved-address))
{:test {}
:prod {}}
(data-store/rpc->saved-addresses raw-saved-addresses))]
{:db (assoc-in db [:wallet :saved-addresses] saved-addresses)}))
[_ [raw-saved-addresses]]
(let [saved-addresses (data-store/rpc->saved-addresses raw-saved-addresses)]
{:fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]}))
(rf/reg-event-fx :wallet/get-saved-addresses-success get-saved-addresses-success)
@@ -52,15 +66,17 @@
(rf/reg-event-fx :wallet/get-saved-addresses get-saved-addresses)
(defn delete-saved-address-success
[_ [toast-message]]
{:fx [[:dispatch [:wallet/get-saved-addresses]]
[:dispatch [:hide-bottom-sheet]]
[:dispatch-later
{:ms 100
:dispatch [:toasts/upsert
{:type :positive
:theme :dark
:text toast-message}]}]]})
[{:keys [db]} [{:keys [address test-networks-enabled? toast-message]}]]
(let [db-key (if test-networks-enabled? :test :prod)
saved-address (get-in db [:wallet :saved-addresses db-key address])]
{:fx [[:dispatch [:wallet/reconcile-saved-addresses [(assoc saved-address :removed? true)]]]
[:dispatch [:hide-bottom-sheet]]
[:dispatch-later
{:ms 100
:dispatch [:toasts/upsert
{:type :positive
:theme :dark
:text toast-message}]}]]}))
(rf/reg-event-fx :wallet/delete-saved-address-success delete-saved-address-success)
@@ -82,7 +98,10 @@
{:fx [[:json-rpc/call
[{:method "wakuext_deleteSavedAddress"
:params [address test-networks-enabled?]
:on-success [:wallet/delete-saved-address-success toast-message]
:on-success [:wallet/delete-saved-address-success
{:address address
:test-networks-enabled? test-networks-enabled?
:toast-message toast-message}]
:on-error [:wallet/delete-saved-address-failed]}]]]}))
(rf/reg-event-fx :wallet/delete-saved-address delete-saved-address)
@@ -2,7 +2,8 @@
(:require
[cljs.test :refer-macros [deftest is testing]]
matcher-combinators.test
[status-im.contexts.settings.wallet.saved-addresses.events :as events]))
[status-im.contexts.settings.wallet.saved-addresses.events :as events]
[status-im.contexts.wallet.data-store :as data-store]))
(deftest get-saved-addresses-test
(testing "get saved addresses - dispatches RPC call"
@@ -15,7 +16,7 @@
:on-error [:wallet/saved-addresses-rpc-error :get-saved-addresses]}]]]]
(is (match? expected-fx result-fx)))))
(def saved-address-1
(def saved-address-rpc-1
{:isTest false
:address "0x1"
:mixedcaseAddress "0x1"
@@ -26,21 +27,45 @@
:colorId "purple"
:removed false})
(def saved-address-1
{:test? true
:address "0x1"
:mixedcase-address "0x1"
:chain-short-names "eth:oeth:"
:network-preferences-names `(:mainnet :optimism)
:name "Bob"
:created-at 1716826714
:ens ""
:ens? false
:customization-color :blue
:removed? false})
(def saved-address-2
{:isTest true
:address "0x2"
:mixedcaseAddress "0x2"
:chainShortNames "eth:arb1:oeth:"
:name "Bob"
:createdAt 1716826714
:ens ""
:colorId "blue"
:removed false})
{:test? false
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
:network-preferences-names `(:mainnet :arbitrum :optimism)
:name "Alicia Keys"
:created-at 1716826806
:ens "alicia.eth"
:ens? true
:customization-color :purple
:removed? false})
(deftest get-saved-addresses-success-test
(let [cofx {:db {}}
raw-saved-addresses [saved-address-rpc-1]
effects (events/get-saved-addresses-success cofx [raw-saved-addresses])
saved-addresses (data-store/rpc->saved-addresses raw-saved-addresses)
result-fx (:fx effects)
expected-fx [[:dispatch [:wallet/reconcile-saved-addresses saved-addresses]]]]
(is (match? expected-fx result-fx))))
(deftest reconcile-saved-addresses-test
(testing "no saved addresses"
(let [cofx {:db {}}
effects (events/get-saved-addresses-success cofx nil)
effects (events/reconcile-saved-addresses cofx nil)
result-db (:db effects)
expected-db {:wallet {:saved-addresses {:test {}
:prod {}}}}]
@@ -48,15 +73,15 @@
(testing "one test saved address"
(let [cofx {:db {}}
effects (events/get-saved-addresses-success cofx [[saved-address-2]])
effects (events/reconcile-saved-addresses cofx [[saved-address-1]])
result-db (:db effects)
expected-db {:wallet {:saved-addresses
{:test {"0x2" {:test? true
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
{:test {"0x1" {:test? true
:address "0x1"
:mixedcase-address "0x1"
:chain-short-names "eth:oeth:"
:ens? false
:network-preferences-names `(:mainnet :arbitrum :optimism)
:network-preferences-names `(:mainnet :optimism)
:name "Bob"
:created-at 1716826714
:ens ""
@@ -67,29 +92,73 @@
(testing "two saved addresses (test and prod)"
(let [cofx {:db {}}
effects (events/get-saved-addresses-success cofx [[saved-address-1 saved-address-2]])
effects (events/reconcile-saved-addresses cofx [[saved-address-1 saved-address-2]])
result-db (:db effects)
expected-db {:wallet {:saved-addresses
{:test {"0x2" {:test? true
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
:network-preferences-names `(:mainnet :arbitrum :optimism)
{:test {"0x1" {:test? true
:address "0x1"
:mixedcase-address "0x1"
:chain-short-names "eth:oeth:"
:ens? false
:network-preferences-names `(:mainnet :optimism)
:name "Bob"
:created-at 1716826714
:ens ""
:customization-color :blue
:removed? false}}
:prod {"0x1" {:test? false
:address "0x1"
:mixedcase-address "0x1"
:prod {"0x2" {:test? false
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
:network-preferences-names `(:mainnet :arbitrum :optimism)
:ens? false
:name "Amy"
:ens? true
:name "Alicia Keys"
:created-at 1716826806
:ens ""
:ens "alicia.eth"
:customization-color :purple
:removed? false}}}}}]
(is (match? expected-db result-db))))
(testing "remove a test saved addresses"
(let [cofx {:db {:wallet {:saved-addresses
{:test {"0x1" {:test? true
:address "0x1"
:mixedcase-address "0x1"
:chain-short-names "eth:oeth:"
:ens? false
:network-preferences-names `(:mainnet :optimism)
:name "Bob"
:created-at 1716826714
:ens ""
:customization-color :blue
:removed? false}}
:prod {"0x2" {:test? false
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
:network-preferences-names `(:mainnet :arbitrum
:optimism)
:ens? true
:name "Alicia Keys"
:created-at 1716826806
:ens "alicia.eth"
:customization-color :purple
:removed? false}}}}}}
effects (events/reconcile-saved-addresses cofx
[[(assoc saved-address-1 :removed? true)
saved-address-2]])
result-db (:db effects)
expected-db {:wallet {:saved-addresses
{:test {}
:prod {"0x2" {:test? false
:address "0x2"
:mixedcase-address "0x2"
:chain-short-names "eth:arb1:oeth:"
:network-preferences-names `(:mainnet :arbitrum :optimism)
:ens? true
:name "Alicia Keys"
:created-at 1716826806
:ens "alicia.eth"
:customization-color :purple
:removed? false}}}}}]
(is (match? expected-db result-db)))))
@@ -141,7 +210,10 @@
expected-fx [[:json-rpc/call
[{:method "wakuext_deleteSavedAddress"
:params [address test-networks-enabled?]
:on-success [:wallet/delete-saved-address-success toast-message]
:on-success [:wallet/delete-saved-address-success
{:address address
:test-networks-enabled? test-networks-enabled?
:toast-message toast-message}]
:on-error [:wallet/delete-saved-address-failed]}]]]]
(is (match? expected-fx result-fx)))))
@@ -109,7 +109,7 @@
:on-press open-show-address-qr
:accessibility-label :show-address-qr-code}
{:icon :i/edit
:label (i18n/label :t/edit-account)
:label (i18n/label :t/edit-details)
:blur? true
:on-press open-edit-saved-address
:accessibility-label :edit-saved-address}
@@ -3,6 +3,7 @@
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.contexts.syncing.device.view :as device]
[status-im.contexts.syncing.syncing-devices-list.style :as style]
[utils.i18n :as i18n]
@@ -13,19 +14,31 @@
(rf/dispatch [:navigate-back]))
(defn open-setup-syncing
[]
(rf/dispatch [:open-modal :settings-setup-syncing]))
[customization-color]
(rf/dispatch
[:show-bottom-sheet
{:theme :dark
:shell? true
:content
(fn [] [check-before-syncing/view
{:customization-color customization-color
:on-submit #(rf/dispatch [:open-modal :settings-setup-syncing])}])}]))
(defn view
[]
(let [devices (rf/sub [:pairing/installations])
devices-with-button (map #(assoc % :show-button? true) devices)
user-device (first devices-with-button)
other-devices (rest devices-with-button)
profile-color (rf/sub [:profile/customization-color])
{:keys [paired-devices unpaired-devices]} (group-by
#(if (:enabled? %) :paired-devices :unpaired-devices)
other-devices)]
(let [devices (rf/sub [:pairing/installations])
devices-with-button (map #(assoc % :show-button? true) devices)
user-device (first devices-with-button)
other-devices (rest devices-with-button)
profile-color (rf/sub [:profile/customization-color])
open-setup-syncing-with-customization-color (rn/use-callback (partial open-setup-syncing
profile-color)
[profile-color])
{:keys [paired-devices unpaired-devices]} (group-by
#(if (:enabled? %)
:paired-devices
:unpaired-devices)
other-devices)]
[quo/overlay {:type :shell :top-inset? true}
[quo/page-nav
{:type :no-title
@@ -47,7 +60,7 @@
:type :primary
:customization-color profile-color
:icon-only? true
:on-press open-setup-syncing}
:on-press open-setup-syncing-with-customization-color}
:i/add]]
[device/view (merge user-device {:this-device? true})]
(when (seq paired-devices)
@@ -11,9 +11,7 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- on-collectible-press
[{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]))
(def on-collectible-press #(rf/dispatch [:wallet/navigate-to-collectible-details %]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details id]}]
@@ -103,8 +103,8 @@
(when activity-state
[quo/info-message
(assoc props
:style style/info-message
:size :default)
:container-style style/info-message
:size :default)
(i18n/label message)])))
(defn view
@@ -163,7 +163,7 @@
{:accessibility-label :error-message
:size :default
:icon :i/info
:type :error
:style style/info-message}
:status :error
:container-style style/info-message}
@validation-msg]
[activity-indicator activity-state])]]))))
[activity-indicator])]]))))
@@ -117,12 +117,12 @@
{:weight :monospace}
(:address derivation-path)]]
[quo/info-message
{:type (case state
:has-activity :success
:no-activity :warning
:default)
:icon (if (= state :scanning) :i/scanning :i/done)
:style style/info}
{:status (case state
:has-activity :success
:no-activity :warning
:default)
:icon (if (= state :scanning) :i/scanning :i/done)
:style style/info}
(i18n/label (case state
:has-activity :t/address-activity
:no-activity :t/address-no-activity
@@ -71,7 +71,7 @@
(rf/reg-event-fx :wallet/seed-phrase-entered seed-phrase-entered)
(defn store-account-generated
(defn store-account-generated-with-mnemonic
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
(let [new-account (update new-account-data :mnemonic security/mask-data)]
{:db (-> db
@@ -85,20 +85,21 @@
:random-phrase))
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]}))
(rf/reg-event-fx :wallet/store-account-generated store-account-generated)
(rf/reg-event-fx :wallet/store-account-generated-with-mnemonic store-account-generated-with-mnemonic)
(defn generate-account-for-keypair
(defn generate-account-for-keypair-with-mnemonic
[{:keys [db]} [{:keys [keypair-name]}]]
(let [seed-phrase (-> db :wallet :ui :create-account :new-keypair :seed-phrase)]
{:fx [[:effects.wallet/create-account-from-mnemonic
{:mnemonic-phrase (security/safe-unmask-data seed-phrase)
:paths [constants/path-default-wallet]
:on-success (fn [new-account-data]
(rf/dispatch [:wallet/store-account-generated
(rf/dispatch [:wallet/store-account-generated-with-mnemonic
{:new-account-data new-account-data
:keypair-name keypair-name}]))}]]}))
(rf/reg-event-fx :wallet/generate-account-for-keypair generate-account-for-keypair)
(rf/reg-event-fx :wallet/generate-account-for-keypair-with-mnemonic
generate-account-for-keypair-with-mnemonic)
(defn clear-create-account-data
[{:keys [db]}]
@@ -159,14 +160,19 @@
(rf/reg-event-fx
:wallet/create-keypair-with-account
(fn [{db :db} [password account-preferences]]
(let [{:keys [keypair-name
(let [{:keys [workflow
keypair-name
new-account-data]} (-> db :wallet :ui :create-account :new-keypair)
keypair-type (if (= workflow :workflow/new-keypair.import-private-key)
:key
:seed)
keypair-with-account (create-account.utils/prepare-new-account
{:keypair-name keypair-name
:keypair-type keypair-type
:account-data new-account-data
:account-preferences account-preferences})
new-address (some-> new-account-data
(create-account.utils/first-derived-account)
(create-account.utils/first-derived-account keypair-type)
(:address)
(string/lower-case))
unmasked-password (security/safe-unmask-data password)]
@@ -176,7 +182,7 @@
:on-success [:wallet/add-account-success new-address]
:on-error #(log/error "Failed to add Keypair and create account" %)}]]]})))
(defn import-and-create-keypair-with-account
(defn import-mnemonic-and-create-keypair-with-account
[{db :db} [{:keys [password account-preferences]}]]
(let [account-data (-> db :wallet :ui :create-account :new-keypair :new-account-data)
unmasked-mnemonic (security/safe-unmask-data (:mnemonic account-data))
@@ -187,7 +193,8 @@
:on-success #(rf/dispatch
[:wallet/create-keypair-with-account password account-preferences])}]]]}))
(rf/reg-event-fx :wallet/import-and-create-keypair-with-account import-and-create-keypair-with-account)
(rf/reg-event-fx :wallet/import-mnemonic-and-create-keypair-with-account
import-mnemonic-and-create-keypair-with-account)
(rf/reg-event-fx
:wallet/derive-address-and-add-account
@@ -206,3 +213,49 @@
:on-error [:wallet/log-rpc-error
{:event :wallet/derive-address-and-add-account
:params [derived-from-address [derivation-path]]}]}]]]}))
(defn import-private-key-and-create-keypair-with-account
[{:keys [db]} [{:keys [password account-preferences]}]]
(let [private-key (get-in db
[:wallet :ui :create-account :new-keypair
:new-account-data :private-key])
unmasked-private-key (security/safe-unmask-data private-key)
unmasked-password (security/safe-unmask-data password)]
{:json-rpc/call
[{:method "accounts_importPrivateKey"
:params [unmasked-private-key unmasked-password]
:on-success [:wallet/create-keypair-with-account password account-preferences]
:on-error #(log/error "Failed to import private key" %)}]}))
(rf/reg-event-fx
:wallet/import-private-key-and-create-keypair-with-account
import-private-key-and-create-keypair-with-account)
(defn store-account-generated-with-private-key
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
{:db (-> db
(update-in [:wallet :ui :create-account :new-keypair]
assoc
:new-account-data new-account-data
:keypair-name keypair-name)
(update-in [:wallet :ui :create-account :new-keypair]
dissoc
:private-key))
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]})
(rf/reg-event-fx :wallet/store-account-generated-with-private-key
store-account-generated-with-private-key)
(rf/reg-event-fx
:wallet/import-private-key-and-generate-account-for-keypair
(fn [{:keys [db]} [{:keys [keypair-name]}]]
(let [private-key (get-in db [:wallet :ui :create-account :private-key])]
{:db (assoc-in db
[:wallet :ui :create-account :new-keypair :workflow]
:workflow/new-keypair.import-private-key)
:fx [[:effects.wallet/create-account-from-private-key
{:private-key private-key
:on-success (fn [new-account-data]
(rf/dispatch [:wallet/store-account-generated-with-private-key
{:keypair-name keypair-name
:new-account-data new-account-data}]))}]]})))
@@ -37,7 +37,7 @@
{:new-account-data {"test" "data"
:mnemonic masked-mnemonic}
:keypair-name "new-keypair-name"}}}}}
effects (events/store-account-generated {:db db} props)
effects (events/store-account-generated-with-mnemonic {:db db} props)
result-db (:db effects)
remove-mnemonic #(update-in %
[:wallet :ui :create-account :new-keypair :new-account-data]
@@ -61,7 +61,7 @@
expected-effects [[:effects.wallet/create-account-from-mnemonic
{:mnemonic-phrase "test-secret"
:paths [constants/path-default-wallet]}]]
effects (events/generate-account-for-keypair {:db db} props)]
effects (events/generate-account-for-keypair-with-mnemonic {:db db} props)]
(is (match?
(update-in effects [:fx 0 1] dissoc :on-success)
{:fx expected-effects}))
@@ -63,31 +63,31 @@
(let [{:keys [message] :as props}
(case state
:scanning
{:type :info
{:status :default
:icon :i/scanning
:message :t/scanning-for-activity}
:inactive-address
{:type :warning
{:status :warning
:icon :i/info
:message :t/this-account-has-no-activity}
:active-address
{:type :success
{:status :success
:icon :i/done
:message :t/this-address-has-activity}
:invalid-private-key
{:type :error
{:status :error
:icon :i/info
:message :t/invalid-private-key}
nil)]
(when props
[quo/info-message
(assoc props
:size :default
:style style/indicator)
(-> props
(assoc :size :default :container-style style/indicator)
(dissoc :message))
(i18n/label message)])))
(defn on-unmount

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