Compare commits

...
Author SHA1 Message Date
Prem Chaitanya Prathi ef1aafa644 feat: changes to publish to 2 peers for lightpush and not use store confirmations 2024-07-12 10:11:43 +05:30
Icaro Motta 54e4b597ed chore(communities): Hide non-implemented tabs in Discover communities (#20684)
Tabs "Open" and "Gated" in Discover communities screen were never implemented in
the code, they are dummies. We now hide them under the flag
config/show-not-implemented-features?, which is disabled for users.

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

To avoid regressions and be quicker, I opted to not remove the "All" tab even
though is the only one shown now, as that would require me to check non-trivial
code due to the fact that the tabs can be sticky as the user scrolls.
2024-07-11 22:38:18 -03:00
Icaro Motta 0b5dac0ad0 feat(settings): Revamp legacy Privacy and security settings (#20671)
Revamps the legacy "Privacy and security" screen to meet the new designs.

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

- Removed setting "Set dApp access permissions" (won't be used anymore).
- Removed setting "Display collectibles" (won't be used anymore).
- Removed setting "Chat link previews setting" (they already had no effect).
- Removed "Reset password setting". This setting is already supported in Profile
  > Password > Change password.
- Removed "Delete my profile". Profile deletion is already supported in the
  login screen.
- Moved setting "Show your profile picture" to Profile > Privacy and security.
- Moved setting "Accept new chats from <XYZ>" to "Allow new contact requests" in
  Profile > Messages. Now it's just a toggle.
- Moved Block screenshots (Android) or Hide Preview (iOS) which are both
  accessible in Profile > Privacy and security.
- Created function utils.navigation/navigate-back, but I only used this in 2
  namespaces to keep the PR under scope.

Areas that may be impacted: old legacy settings that are still relevant.
2024-07-11 22:23:17 -03:00
Mohamed Javid 180065129f fix(saved-addresses): clean QR scanned address (#20699)
This commit cleans the scanned QR address/result on the unmount of the add new saved address flow.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-07-11 20:01:55 +05:30
Mohamed Javid 866b854ee0 fix(key-pairs)_: error message on scanning different key pair QR (#20612)
This commit:

- update the connection string validation method to use the method from status-go
- updates the error message if the user tries to scan a different key pair QR for importing a missing key pair
- updates the text for exporting an individual key pair

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-07-11 15:55:00 +05:30
Shivek KhuranaandLungu Cristian 072370b0d6 🙅 Gracefully reject proposals and requests (#20649)
* 🙅 Gracefully reject proposals and requests

* 🔑 Remove redudant fx, send correct error

* ➡️ Docstring to comment

---------

Co-authored-by: Lungu Cristian <lungucristian95@gmail.com>
2024-07-11 13:03:14 +03:00
Shivek KhuranaandLungu Cristian d74edff9b9 2️⃣ Use v2 api for persisting sessions (#20648)
* 2️⃣ Use v2 api for persisting sessions

* 🗑️ Remove traces of REPL and v2 suffix

---------

Co-authored-by: Lungu Cristian <lungucristian95@gmail.com>
2024-07-11 12:50:42 +03:00
Andrea Maria Piana 0a0591f67a Add centralized metrics
https://github.com/status-im/status-go/compare/6e056348...1ef2434b

This commit adds support for pushing centralized metrics to mixpanel.

It uses an interceptor and only picks a few selected events to push
through.

In order to test:

1) Create an account in the app
2) Go to Settings->Privacy
3) Enable metrics

You should now see the events on the mixpanel dashboard (login with your
status-im account for access).
Only some example events are tracked, they are just for testing
2024-07-11 10:06:46 +01:00
Andrea Maria Piana 7a8db689f4 enable light client by default 2024-07-11 09:01:23 +01:00
John NgeiandYevheniia Berdnyk 311fde9409 chore: remove identifiers screens (#20503)
* chore: remove identifiers screens so users are navigated straight to enable notifications during onboarding

* removed navigated back button from enable notification screen

* fix top margin

* e2e: updated sign in flow

* make lint-fix

---------

Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-07-11 02:09:03 +02:00
Yevheniia Berdnyk f89b66f562 e2e: adding android.gpu.mode capability to fix emulators crash 2024-07-11 02:43:32 +03:00
Yevheniia Berdnyk d179cbf59b e2e: updated discover communities test 2024-07-10 19:53:48 +05:30
Parvesh Monu 7ff7e78691 fix user lands on the Home screen after closing a community opened from Discover Communities 2024-07-10 19:53:47 +05:30
Omar Basem 6c352397ab fix(wallet): asset sorting (#20659)
* fix(wallet): asset sorting (#20659)
2024-07-10 14:49:24 +04: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
237 changed files with 4408 additions and 2461 deletions
-1
View File
@@ -26,7 +26,6 @@ APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
COMMANDS_ENABLED=1
TWO_MINUTES_SYNCING=1
SWAP_ENABLED=1
-1
View File
@@ -18,6 +18,5 @@ PARTITIONED_TOPIC=0
ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
+6
View File
@@ -457,6 +457,12 @@ android-tail-geth: export VERSION ?= debug
android-tail-geth:
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-clean-geth: export TARGET := android-sdk
android-clean-geth: export VERSION ?= debug
android-clean-geth:
adb shell 'rm /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-logcat: export TARGET := android-sdk
android-logcat: ##@other Read status-mobile logs from Android phone using adb
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
+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
@@ -246,6 +246,14 @@ class AccountManager(private val reactContext: ReactApplicationContext) : ReactC
utils.executeRunnableStatusGoMethod({ Statusgo.openAccounts(rootDir) }, callback)
}
@ReactMethod
private fun initializeApplication(request: String, callback: Callback) {
Log.d(TAG, "initializeApplication")
Log.d(TAG, "[Initializing application $request")
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
}
@ReactMethod
fun logout() {
Log.d(TAG, "logout")
@@ -76,6 +76,16 @@ class StatusModule(private val reactContext: ReactApplicationContext, private va
utils.executeRunnableStatusGoMethod({ Statusgo.getNodeConfig() }, callback)
}
@ReactMethod
fun addCentralizedMetric(request: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.addCentralizedMetric(request) }, callback)
}
@ReactMethod
fun toggleCentralizedMetrics(request: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.toggleCentralizedMetrics(request) }, callback)
}
@ReactMethod
fun deleteImportedKey(keyUID: String, address: String, password: String, callback: Callback) {
val keyStoreDir = utils.getKeyStorePath(keyUID)
@@ -153,4 +153,9 @@ class Utils(private val reactContext: ReactApplicationContext) : ReactContextBas
return strArray
}
@ReactMethod(isBlockingSynchronousMethod = true)
fun validateConnectionString(connectionString: String): String {
return Statusgo.validateConnectionString(connectionString)
}
}
@@ -195,6 +195,15 @@ RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
callback(@[result]);
}
RCT_EXPORT_METHOD(initializeApplication:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"initializeApplication() method called");
#endif
NSString *result = StatusgoInitializeApplication(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"OpenAccounts() method called");
@@ -176,6 +176,24 @@ RCT_EXPORT_METHOD(appStateChange:(NSString *)type) {
StatusgoAppStateChange(type);
}
RCT_EXPORT_METHOD(addCentralizedMetric:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"addCentralizedMetric() method called");
#endif
NSString *result = StatusgoAddCentralizedMetric(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(toggleCentralizedMetrics:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"toggleCentralizedMetrics() method called");
#endif
NSString *result = StatusgoToggleCentralizedMetrics(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(startLocalNotifications) {
#if DEBUG
NSLog(@"StartLocalNotifications() method called");
@@ -128,4 +128,8 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(validateConnectionString:(NSString *)cs) {
return StatusgoValidateConnectionString(cs);
}
@end
+32 -1
View File
@@ -302,6 +302,36 @@ void _MultiAccountStoreAccount(const FunctionCallbackInfo<Value>& args) {
delete c;
}
void _InitializeApplication(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for InitializeApplication")));
return;
}
// Check the argument types
if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for request")));
return;
}
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;
// Call exported Go function, which returns a C string
char *c = InitializeApplication(arg0);
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}
void _InitKeystore(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
@@ -1935,6 +1965,7 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "multiAccountStoreDerivedAccounts", _MultiAccountStoreDerivedAccounts);
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
NODE_SET_METHOD(exports, "fleets", _Fleets);
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
@@ -1972,7 +2003,7 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "signTypedData", _SignTypedData);
NODE_SET_METHOD(exports, "sendTransaction", _SendTransaction);
NODE_SET_METHOD(exports, "appStateChange", _AppStateChange);
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
NODE_SET_METHOD(exports, "validateNodeConfig", _ValidateNodeConfig);
NODE_SET_METHOD(exports, "hashTypedData", _HashTypedData);
NODE_SET_METHOD(exports, "recover", _Recover);
+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

+2
View File
@@ -45,6 +45,8 @@ SECRETS_ENV_VARS=(
'INFURA_TOKEN'
'INFURA_TOKEN_SECRET'
'OPENSEA_API_KEY'
'MIXPANEL_APP_ID'
'MIXPANEL_TOKEN'
'POKT_TOKEN'
)
+6
View File
@@ -67,6 +67,8 @@
:closure-defines
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
@@ -102,6 +104,8 @@
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
@@ -143,6 +147,8 @@
status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
+1 -3
View File
@@ -26,7 +26,6 @@
legacy.status-im.ui.components.invite.events
[legacy.status-im.ui.components.react :as react]
legacy.status-im.ui.screens.notifications-settings.events
legacy.status-im.ui.screens.privacy-and-security-settings.events
[legacy.status-im.utils.dimensions :as dimensions]
legacy.status-im.utils.logging.core
[legacy.status-im.utils.utils :as utils]
@@ -108,8 +107,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]}]
@@ -120,12 +120,3 @@
{:events [:multiaccounts.ui/switch-backup-enabled]}
[cofx enabled?]
(multiaccount-update cofx :backup-enabled? enabled? {}))
(rf/defn toggle-opensea-nfts-visibility
{:events [::toggle-opensea-nfts-visiblity]}
[cofx visible?]
(rf/merge cofx
{:db (assoc-in (:db cofx) [:profile/profile :opensea-enabled?] visible?)
;; need to add fully qualified namespace to counter circular deps
:dispatch [:legacy.status-im.wallet.core/fetch-collectibles-collection]}
(multiaccount-update :opensea-enabled? visible? {})))
+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,11 +0,0 @@
(ns legacy.status-im.ui.screens.dapps-permissions.styles
(:require
[legacy.status-im.ui.components.colors :as colors]))
(def icon-container
{:width 40
:height 40
:border-radius 20
:background-color colors/gray-lighter
:align-items :center
:justify-content :center})
@@ -1,64 +0,0 @@
(ns legacy.status-im.ui.screens.dapps-permissions.views
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.icons.icons :as icons]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.components.topbar :as topbar]
[legacy.status-im.ui.screens.dapps-permissions.styles :as styles]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
(defn d-icon
[]
[react/view styles/icon-container
[icons/icon :main-icons/dapp {:color colors/gray}]])
(defn prepare-items
[{:keys [dapp permissions]}]
{:title dapp
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :manage-dapps-permissions
{:dapp dapp :permissions permissions}])
:icon [d-icon]})
(defn prepare-items-manage
[name]
(fn [permission]
{:title (cond
(= permission constants/dapp-permission-web3)
name
(= permission constants/dapp-permission-contact-code)
(i18n/label :t/contact-code))
:size :small
:accessory [icons/icon :main-icons/check {}]}))
(views/defview dapps-permissions
[]
(views/letsubs [permissions [:dapps/permissions]]
[list/flat-list
{:data (vec (map prepare-items (vals permissions)))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item}]))
(views/defview manage
[]
(views/letsubs [{:keys [dapp permissions]} [:get-screen-params]
{:keys [name]} [:dapps-account]]
[:<>
[topbar/topbar {:title dapp}]
[list/flat-list
{:data (vec (map (prepare-items-manage name) permissions))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item}]
[react/view
{:padding-vertical 16
:padding-horizontal 16}
[quo/button
{:theme :negative
:on-press #(re-frame/dispatch [:dapps/revoke-access dapp])}
(i18n/label :t/revoke-access)]]]))
@@ -1,13 +0,0 @@
(ns legacy.status-im.ui.screens.link-previews-settings.styles)
(def link-preview-settings-image
{:height 100
:align-self :center
:margin-top 16})
(def whitelist-container
{:flex-direction :row
:justify-content :space-between})
(def enable-all
{:align-self :flex-end})
@@ -1,67 +0,0 @@
(ns legacy.status-im.ui.screens.link-previews-settings.views
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.react-native.resources :as resources]
[legacy.status-im.ui.components.core :as components]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.link-previews-settings.styles :as styles]
[quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.contexts.chat.messenger.messages.link-preview.events]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn prepare-urls-items-data
[link-previews-enabled-sites]
(fn [{:keys [title address]}]
(let [enabled? (contains? link-previews-enabled-sites title)]
{:title title
:subtitle address
:size :small
:accessory :switch
:active (contains? link-previews-enabled-sites title)
:on-press #(re-frame/dispatch
[:chat.ui/enable-link-previews title ((complement boolean) enabled?)])})))
(views/defview link-previews-settings
[]
(views/letsubs [link-previews-whitelist [:link-previews-whitelist]
link-previews-enabled-sites [:link-preview/enabled-sites]]
(let [all-enabled (= (count link-previews-whitelist) (count link-previews-enabled-sites))]
[:<>
[quo/page-nav
{:type :title
:title (i18n/label :t/chat-link-previews)
:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
[react/image
{:source (resources/get-theme-image :unfurl)
:style styles/link-preview-settings-image}]
[components/text {:style {:margin 16}}
(i18n/label :t/you-can-choose-preview-websites)]
[components/separator {:style {:margin-vertical 8}}]
[react/view styles/whitelist-container
[components/list-header (i18n/label :t/websites)]
(when (> (count link-previews-whitelist) 1)
[components/button
{:on-press #(re-frame/dispatch [:chat.ui/enable-all-link-previews
link-previews-whitelist
(not all-enabled)])
:type :secondary
:style styles/enable-all}
(if all-enabled
(i18n/label :t/disable-all)
(i18n/label :t/enable-all))])]
[list/flat-list
{:data (vec (map (prepare-urls-items-data link-previews-enabled-sites)
link-previews-whitelist))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item
:footer [quo/text
{:color :secondary
:style {:margin 16}} (i18n/label :t/previewing-may-share-metadata)]}]])))
@@ -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)]]]))
@@ -1,81 +0,0 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile
(:require
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[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]
[legacy.status-im.ui.screens.privacy-and-security-settings.events :as delete-profile]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.security.core :as security]))
(defn valid-password?
[password]
(>= (count password) 6))
(defn on-delete-profile
[password]
#(do
(re-frame/dispatch
[::delete-profile/delete-profile @password])
(reset! password nil)))
(defn delete-profile
[]
(let [password (reagent/atom nil)
text-input-ref (atom nil)]
(fn []
(let [profile @(re-frame/subscribe [:profile/profile])
error @(re-frame/subscribe [:delete-profile/error])
keep-keys-on-keycard? @(re-frame/subscribe
[:delete-profile/keep-keys-on-keycard?])]
(when (and @text-input-ref error (not @password))
(.clear ^js @text-input-ref))
[react/keyboard-avoiding-view {:style {:flex 1}}
[react/scroll-view {:style {:flex 1}}
[react/view {:style {:align-items :center}}
[quo/text
{:weight :bold
:size :x-large}
(i18n/label :t/delete-profile)]]
[list.item/list-item
{:title (profile.utils/displayed-name profile)
:icon [chat-icon.screen/contact-icon-contacts-tab profile]}]
[quo/text
{:style {:margin-horizontal 24}
:align :center
:color :negative}
(i18n/label :t/delete-profile-warning)]
[quo/text-input
{:style {:margin-horizontal 36
:margin-top 36}
:show-cancel false
:secure-text-entry true
:return-key-type :next
:on-submit-editing nil
:auto-focus true
:on-change-text #(reset! password (security/mask-data %))
:bottom-value 36
:get-ref #(reset! text-input-ref %)
:error (when (and error (not @password))
(if (= :wrong-password error)
(i18n/label :t/wrong-password)
(str error)))}]]
[react/view {:style {:align-items :center}}
[quo/separator]
(when (not keep-keys-on-keycard?)
[quo/text
{:style {:margin-horizontal 24 :margin-bottom 16}
:align :center
:color :negative}
(i18n/label :t/delete-profile-warning)])
[react/view
{:style {:margin-vertical 8}}
[quo/button
{:on-press (on-delete-profile password)
:theme :negative
:accessibility-label :delete-profile-confirm
:disabled ((complement valid-password?) @password)}
(i18n/label :t/delete-profile)]]]]))))
@@ -1,73 +0,0 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.events
(:require
[clojure.string :as string]
[legacy.status-im.utils.deprecated-types :as types]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(defn safe-blank?
[s]
(or (not s)
(string/blank? s)))
(re-frame/reg-fx
::delete-profile
(fn [{:keys [address key-uid callback masked-password]}]
(let [hashed-password
(-> masked-password
security/safe-unmask-data
native-module/sha3)]
(native-module/verify
address
hashed-password
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(log/info "[delete-profile] verify-password" result error)
(if-not (safe-blank? error)
(callback :wrong-password nil)
(native-module/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(callback error nil)))))))))))
(rf/defn delete-profile
{:events [::delete-profile]}
[{:keys [db] :as cofx} masked-password]
(log/info "[delete-profile] delete")
(let [{:keys [key-uid wallet-root-address]} (:profile/profile db)]
{:db (dissoc db :delete-profile/error)
::delete-profile
{:masked-password masked-password
:key-uid key-uid
:address wallet-root-address
:callback
(fn [error result]
(log/info "[delete-profile] callback" error)
(if (safe-blank? error)
(re-frame/dispatch [::on-delete-profile-success result])
(re-frame/dispatch [::on-delete-profile-failure error])))}}))
(rf/defn on-delete-profile-success
{:events [::on-delete-profile-success]}
[cofx]
(log/info "[delete-profile] on-success")
{:effects.utils/show-popup
{:title (i18n/label :t/profile-deleted-title)
:content (i18n/label :t/profile-deleted-content)
:on-dismiss #(re-frame/dispatch [:logout])}})
(rf/defn on-delete-profile-failure
{:events [::on-delete-profile-failure]}
[{:keys [db]} error]
(log/info "[delete-profile] on-failure" error)
{:db (assoc db :delete-profile/error error)})
(rf/defn keep-keys-on-keycard
{:events [::keep-keys-on-keycard]}
[{:keys [db] :as cofx} checked?]
{:db (assoc-in db [:delete-profile/keep-keys-on-keycard?] checked?)})
@@ -1,34 +0,0 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[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]
[utils.re-frame :as rf]))
(rf/defn handle-messages-from-contacts-only-switched
{:events [::messages-from-contacts-only-switched]}
[cofx value]
(multiaccounts.update/multiaccount-update cofx
:messages-from-contacts-only
value
{}))
(views/defview messages-from-contacts-only-view
[]
(views/letsubs [{:keys [messages-from-contacts-only]} [:profile/profile]]
[react/view {:margin-top 8}
[list.item/list-item
{:active (not messages-from-contacts-only)
:accessory :radio
:title (i18n/label :t/anyone)
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched false])}]
[list.item/list-item
{:active messages-from-contacts-only
:accessory :radio
:title (i18n/label :t/contacts)
:subtitle (i18n/label :t/messages-from-contacts-only-subtitle)
:subtitle-max-lines 4
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched true])}]]))
@@ -1,175 +0,0 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.views
(:require
[legacy.status-im.multiaccounts.reset-password.core :as reset-password]
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.ui.components.core :as components]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[quo.core :as quo]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.config :as config]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf])
(:require-macros [legacy.status-im.utils.views :as views]))
(defn separator
[]
[components/separator {:style {:margin-vertical 8}}])
(def titles
{constants/profile-pictures-visibility-contacts-only (i18n/label :t/recent-recipients)
constants/profile-pictures-visibility-everyone (i18n/label :t/everyone)
constants/profile-pictures-visibility-none (i18n/label :t/none)
constants/profile-pictures-show-to-contacts-only (i18n/label :t/recent-recipients)
constants/profile-pictures-show-to-everyone (i18n/label :t/everyone)
constants/profile-pictures-show-to-none (i18n/label :t/none)})
(views/defview privacy-and-security
[]
(views/letsubs [{:keys [preview-privacy?
messages-from-contacts-only
webview-allow-permission-requests?
opensea-enabled?
profile-pictures-visibility]}
[:profile/profile]
has-picture [:profile/has-picture]
profile-pictures-show-to [:multiaccount/profile-pictures-show-to]]
[:<>
[quo/page-nav
{:type :no-title
:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
[react/scroll-view {:padding-vertical 8}
[components/list-header (i18n/label :t/privacy)]
[list.item/list-item
{:size :small
:title (i18n/label :t/set-dapp-access-permissions)
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
:accessibility-label :dapps-permissions-button
:chevron true}]
[list.item/list-item
{:size :small
:title (if platform/android?
(i18n/label :t/hide-content-when-switching-apps)
(i18n/label :t/hide-content-when-switching-apps-ios))
:container-margin-bottom 8
:active preview-privacy?
:accessory :switch
:on-press #(re-frame/dispatch
[:profile.settings/change-preview-privacy
((complement boolean) preview-privacy?)])}]
(when config/collectibles-enabled?
[list.item/list-item
{:size :small
:title (i18n/label :t/display-collectibles)
:container-margin-bottom 8
:active opensea-enabled?
:accessory :switch
:on-press #(re-frame/dispatch
[::multiaccounts.update/toggle-opensea-nfts-visiblity
(not opensea-enabled?)])}])
[list.item/list-item
{:size :small
:title (i18n/label :t/chat-link-previews)
:chevron true
:on-press #(re-frame/dispatch [:open-modal :legacy-link-previews-settings])
:accessibility-label :chat-link-previews}]
[list.item/list-item
{:size :small
:title (i18n/label :t/accept-new-chats-from)
:chevron true
:accessory :text
:accessory-text (i18n/label (if messages-from-contacts-only
:t/contacts
:t/anyone))
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
:accessibility-label :accept-new-chats-from}]
[list.item/list-item
{:size :small
:title (i18n/label :t/reset-password)
:chevron true
:accessory :text
:on-press #(do
(re-frame/dispatch [::reset-password/clear-form-vals])
(re-frame/dispatch [:navigate-to :reset-password]))
:accessibility-label :reset-password}]
(when platform/android?
[list.item/list-item
{:size :small
:title (i18n/label :t/webview-camera-permission-requests)
:active webview-allow-permission-requests?
:accessory :switch
:subtitle (i18n/label :t/webview-camera-permission-requests-subtitle)
:subtitle-max-lines 2
:on-press #(re-frame/dispatch
[:profile.settings/profile-update
:webview-allow-permission-requests?
((complement boolean) webview-allow-permission-requests?)])}])
[separator]
[components/list-header (i18n/label :t/privacy-photos)]
[list.item/list-item
{:size :small
:title (i18n/label :t/show-profile-pictures)
:accessibility-label :show-profile-pictures
:accessory :text
:accessory-text (get titles profile-pictures-visibility)
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security-profile-pic])
:chevron true}]
[list.item/list-item
{:size :small
:title (i18n/label :t/show-profile-pictures-to)
:disabled (not has-picture)
:accessibility-label :show-profile-pictures-to
:accessory :text
:accessory-text (get titles profile-pictures-show-to)
:on-press #(re-frame/dispatch [:navigate-to
:privacy-and-security-profile-pic-show-to])
:chevron true}]
[separator]
[list.item/list-item
{:size :small
:theme :negative
:title (i18n/label :t/delete-my-profile)
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
:accessibility-label :dapps-permissions-button
:chevron true}]]]))
(defn ppst-radio-item
[id value]
[list.item/list-item
{:active (= value id)
:accessory :radio
:title (get titles id)
:on-press #(re-frame/dispatch [:profile.settings/change-profile-pictures-show-to id])}])
(views/defview profile-pic-show-to
[]
(views/letsubs [{:keys [profile-pictures-show-to]} [:profile/profile]]
[react/view {:margin-top 8}
[ppst-radio-item constants/profile-pictures-show-to-everyone profile-pictures-show-to]
[ppst-radio-item constants/profile-pictures-show-to-contacts-only profile-pictures-show-to]
[ppst-radio-item constants/profile-pictures-show-to-none profile-pictures-show-to]
[react/view {:style {:margin-horizontal 16}}
[components/text {:color :secondary}
(i18n/label :t/privacy-show-to-warning)]]]))
(defn ppvf-radio-item
[id value]
[list.item/list-item
{:active (= value id)
:accessory :radio
:title (get titles id)
:on-press #(re-frame/dispatch [:profile.settings/profile-update :profile-pictures-visibility id])}])
(views/defview profile-pic
[]
(views/letsubs [{:keys [profile-pictures-visibility]} [:profile/profile]]
[react/view {:margin-top 8}
[ppvf-radio-item constants/profile-pictures-visibility-everyone profile-pictures-visibility]
[ppvf-radio-item constants/profile-pictures-visibility-contacts-only profile-pictures-visibility]
[ppvf-radio-item constants/profile-pictures-visibility-none profile-pictures-visibility]]))
@@ -13,12 +13,6 @@
[]
[rn/scroll-view {:flex 1}
[components/list-header "Legacy settings"]
[list.item/list-item
{:icon :main-icons/security
:title (i18n/label :t/privacy-and-security)
:accessibility-label :privacy-and-security-settings-button
:chevron true
:on-press #(re-frame/dispatch [:open-modal :legacy-privacy-and-security])}]
[list.item/list-item
{:icon :main-icons/mobile
:title (i18n/label :t/sync-settings)
@@ -8,12 +8,10 @@
[legacy.status-im.ui.screens.bug-report :as bug-report]
[legacy.status-im.ui.screens.communities.invite :as communities.invite]
[legacy.status-im.ui.screens.communities.members :as members]
[legacy.status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
[legacy.status-im.ui.screens.default-sync-period-settings.view :as default-sync-period-settings]
[legacy.status-im.ui.screens.fleet-settings.views :as fleet-settings]
[legacy.status-im.ui.screens.glossary.view :as glossary]
[legacy.status-im.ui.screens.help-center.views :as help-center]
[legacy.status-im.ui.screens.link-previews-settings.views :as link-previews-settings]
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
[legacy.status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
@@ -21,10 +19,6 @@
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
[legacy.status-im.ui.screens.pairing.views :as pairing]
[legacy.status-im.ui.screens.peers-stats :as peers-stats]
[legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile]
[legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only :as
messages-from-contacts-only]
[legacy.status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security]
[legacy.status-im.ui.screens.profile.seed.views :as profile.seed]
[legacy.status-im.ui.screens.profile.user.views :as profile.user]
[legacy.status-im.ui.screens.progress.views :as progress]
@@ -94,17 +88,6 @@
:insets {:top? platform/android?}}
:component profile.user/legacy-settings}
;; PRIVACY AND SECURITY
{:name :legacy-privacy-and-security
:options {:topBar {:visible false}
:insets {:top? platform/android?}}
:component privacy-and-security/privacy-and-security}
{:name :legacy-link-previews-settings
:options {:topBar {:visible false}
:insets {:top? platform/android?}}
:component link-previews-settings/link-previews-settings}
;; SYNC
{:name :legacy-sync-settings
:options {:topBar {:visible false}
@@ -150,25 +133,6 @@
{:name :edit-mailserver
:options {:insets {:top? true}}
:component edit-mailserver/edit-mailserver}
{:name :dapps-permissions
:options {:topBar (topbar-options :t/dapps-permissions)
:insets {:top? true}}
:component dapps-permissions/dapps-permissions}
{:name :messages-from-contacts-only
:options {:topBar (topbar-options :t/accept-new-chats-from)
:insets {:top? true}}
:component messages-from-contacts-only/messages-from-contacts-only-view}
{:name :privacy-and-security-profile-pic-show-to
:options {:topbar (topbar-options :t/show-profile-pictures-to)
:insets {:top? true}}
:component privacy-and-security/profile-pic-show-to}
{:name :privacy-and-security-profile-pic
:options {:topBar (topbar-options :t/show-profile-pictures)
:insets {:top? true}}
:component privacy-and-security/profile-pic}
{:name :manage-dapps-permissions
:options {:insets {:top? true}}
:component dapps-permissions/manage}
{:name :rpc-usage-info
:options {:topBar (topbar-options :t/rpc-usage-info)
:insets {:top? true}}
@@ -196,9 +160,6 @@
:options {:topBar (topbar-options :t/reset-password)
:insets {:top? true}}
:component reset-password/reset-password}
{:name :delete-profile
:insets {:bottom? true}
:component delete-profile/delete-profile}
{:name :default-sync-period-settings
:options {:topBar (topbar-options :t/default-sync-period)
:insets {:top? true}}
@@ -128,7 +128,6 @@
:current-chat-id
:network
:network-status
:peers-count
:peers-summary
:sync-state
:view-id
-130
View File
@@ -1,130 +0,0 @@
(ns legacy.status-im.utils.test
(:require
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]))
(def native-status (js/require "../../modules/react-native-status/nodejs/bindings"))
(def fs (js/require "fs"))
(def path (js/require "path"))
(def os (js/require "os"))
(def tmpdir (.tmpdir os))
(def test-dir-prefix (.join path tmpdir "status-mobile-tests"))
(def test-dir (.mkdtempSync fs test-dir-prefix))
(def initialized? (atom false))
(defn signal-received-callback
[a]
(re-frame/dispatch [:signals/signal-received a]))
;; We poll for signals, could not get callback working
(defn init!
[]
(when-not @initialized?
(.setSignalEventCallback native-status)
(reset! initialized? true)
(js/setInterval (fn []
(.pollSignal native-status signal-received-callback)
100))))
(def ui-helper
(clj->js
{:clearCookies identity
:clearStorageAPIs identity}))
(def encryption-utils
(clj->js
{:sha3
(fn [s] (.sha3 native-status s))
:setBlankPreviewFlag
identity
:encodeTransfer
(fn [to-norm amount-hex]
(.encodeTransfer native-status to-norm amount-hex))
:hexToNumber
(fn [hex] (.hexToNumber native-status hex))
:decodeParameters
(fn [decode-param-json]
(.decodeParameters native-status decode-param-json))
:numberToHex
(fn [num-str] (.numberToHex native-status num-str))
:initKeystore
(fn [key-uid callback]
(callback (.initKeystore native-status
(str test-dir "/keystore/" key-uid))))
:multiformatDeserializePublicKey
(fn [public-key deserialization-key callback]
(callback (.multiformatDeserializePublicKey
native-status
public-key
deserialization-key)))}))
(def account-manager
(clj->js
{:openAccounts
(fn [callback]
(callback (.openAccounts native-status test-dir)))
:createAccountAndLogin
(fn [request] (.createAccountAndLogin native-status request))
:logout
(fn [] (.logout native-status))
:multiAccountImportMnemonic
(fn [json callback]
(callback (.multiAccountImportMnemonic native-status json)))
:multiAccountLoadAccount
(fn [json callback]
(callback (.multiAccountLoadAccount native-status json)))
:multiAccountDeriveAddresses
(fn [json callback]
(callback (.multiAccountDeriveAddresses native-status json)))
:multiAccountGenerateAndDeriveAddresses
(fn [json callback]
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
:multiAccountStoreDerived
(fn [json callback]
(callback (.multiAccountStoreDerivedAccounts native-status json)))}))
(def utils
(clj->js
{:backupDisabledDataDir
(fn [] (str test-dir "/backup"))
:keystoreDir (fn [] "")
:toChecksumAddress
(fn [address] (.toChecksumAddress native-status address))
:checkAddressChecksum
(fn [address] (.checkAddressChecksum native-status address))
:validateMnemonic
(fn [json callback] (callback (.validateMnemonic native-status json)))
:isAddress
(fn [address] (.isAddress native-status address))}))
(def log-manager
(clj->js
{:logFileDirectory
(fn [] (str test-dir "/log"))
:initLogging
(fn [enabled mobile-system log-level callback]
(callback (.initLogging native-status
(types/clj->json {:Enabled enabled
:MobileSystem mobile-system
:Level log-level
:File (str test-dir "/geth.log")}))))}))
(def network
(clj->js
{:callPrivateRPC
(fn [payload callback]
(callback (.callPrivateRPC native-status payload)))}))
(def status
(clj->js
{:getNodeConfig
(fn [] (types/clj->json {:WakuV2Config ""}))
:fleets
(fn [] (.fleets native-status))
:startLocalNotifications
identity}))
@@ -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
+21 -5
View File
@@ -72,10 +72,12 @@
(log/debug "[native-module] init-keystore" key-uid)
(.initKeystore ^js (encryption) key-uid callback))
(defn open-accounts
[callback]
(log/debug "[native-module] open-accounts")
(.openAccounts ^js (account-manager) #(callback (types/json->clj %))))
(defn initialize-application
[request callback]
(log/debug "[native-module] initialize-application")
(.initializeApplication ^js (account-manager)
(types/clj->json request)
#(callback (types/json->clj %))))
(defn prepare-dir-and-update-config
[key-uid config callback]
@@ -513,6 +515,14 @@
(let [result (.checkAddressChecksum ^js (utils) address)]
(types/json->clj result)))
(defn toggle-centralized-metrics
[enabled callback]
(.toggleCentralizedMetrics ^js (status) (types/clj->json {:enabled enabled}) callback))
(defn add-centralized-metric
[metric]
(.addCentralizedMetric ^js (status) (types/clj->json metric) #(log/debug "pushed metric" % metric)))
(defn address?
[address]
(log/debug "[native-module] address?")
@@ -533,6 +543,13 @@
(log/debug "[native-module] validate-mnemonic")
(.validateMnemonic ^js (utils) mnemonic callback)))
(defn validate-connection-string
[connection-string]
(log/debug "[native-module] validate-connection-string")
(->> connection-string
(.validateConnectionString ^js (utils))
types/json->clj))
(defn delete-multiaccount
"Delete multiaccount from database, deletes multiaccount's database and
key files."
@@ -643,7 +660,6 @@
(native-utils/promisify-native-module-call create-account-from-private-key private-key))
([private-key callback]
(log/debug "[native-module] create-account-from-private-key")
(.createAccountFromPrivateKey ^js (account-manager)
(types/clj->json {:privateKey private-key})
callback)))
@@ -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
@@ -51,7 +51,7 @@
(defn color
[blur? theme]
{:color (if blur?
colors/white-opa-70
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
(defn label-dot
@@ -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]
+2
View File
@@ -22,6 +22,8 @@
(clj->js {:proposal proposal
:supportedNamespaces supported-namespaces})))
;; Get an error from this list:
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts
(defn get-sdk-error
[error-key]
(getSdkError error-key))
@@ -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]]))
+4 -2
View File
@@ -35,7 +35,9 @@
user-in-syncing-devices-screen? (or (= (:view-id db) :screen/onboarding.syncing-progress)
(= (:view-id db) :screen/profile.profiles)
(= (:view-id db) :screen/onboarding.syncing-progress-intro))
user-in-sign-in-intro-screen? (= (:view-id db) :screen/onboarding.sign-in-intro)]
user-in-sign-in-intro-screen? (= (:view-id db) :screen/onboarding.sign-in-intro)
keystore-files-transfer-action? (= action
constants/local-pairing-action-keystore-files-transfer)]
(merge {:db (cond-> db
connection-success?
(assoc-in [:syncing :pairing-status] :connected)
@@ -61,7 +63,7 @@
(and completed-pairing? receiver?)
{:dispatch [:profile.login/local-paired-user]}
(and error-on-pairing? (some? error))
(and error-on-pairing? (some? error) (not keystore-files-transfer-action?))
{:dispatch [:toasts/upsert
{:type :negative
:text error}]}))))
@@ -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?
+5 -1
View File
@@ -25,6 +25,8 @@
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
(goog-define MIXPANEL_APP_ID "3350627")
(goog-define MIXPANEL_TOKEN "5c73bda2d36a9f688a5ee45641fb6775")
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
@@ -39,6 +41,9 @@
(def opensea-link "https://opensea.io")
(def opensea-tesnet-link "https://testnets.opensea.io")
(def mixpanel-app-id MIXPANEL_APP_ID)
(def mixpanel-token MIXPANEL_TOKEN)
(def opensea-api-key OPENSEA_API_KEY)
(def bootnodes-settings-enabled? (enabled? (get-config :BOOTNODES_SETTINGS_ENABLED "1")))
(def mailserver-confirmations-enabled? (enabled? (get-config :MAILSERVER_CONFIRMATIONS_ENABLED)))
@@ -58,7 +63,6 @@
(def quo-preview-enabled? (enabled? (get-config :ENABLE_QUO_PREVIEW "0")))
(def database-management-enabled? (enabled? (get-config :DATABASE_MANAGEMENT_ENABLED "0")))
(def debug-webview? (enabled? (get-config :DEBUG_WEBVIEW "0")))
(def collectibles-enabled? (enabled? (get-config :COLLECTIBLES_ENABLED "1")))
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
+18 -1
View File
@@ -281,6 +281,9 @@
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
(def ^:const wallet-connect-session-proposal-event "session_proposal")
(def ^:const wallet-connect-session-request-event "session_request")
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
@@ -367,16 +370,18 @@
(def ^:const local-pairing-role-receiver "receiver")
;; sender and receiver events
(def ^:const local-pairing-event-peer-discovered "peer-discovered")
(def ^:const local-pairing-event-connection-success "connection-success")
(def ^:const local-pairing-event-connection-error "connection-error")
(def ^:const local-pairing-event-transfer-success "transfer-success")
(def ^:const local-pairing-event-transfer-error "transfer-error")
(def ^:const local-pairing-event-received-installation "received-installation")
;; receiver events
(def ^:const local-pairing-event-received-account "received-account")
(def ^:const local-pairing-event-process-success "process-success")
(def ^:const local-pairing-event-process-error "process-error")
(def ^:const local-pairing-event-received-installation "received-installation")
(def ^:const local-pairing-event-received-keystore-files "received-keystore-files")
(def ^:const local-pairing-event-errors
#{local-pairing-event-connection-error
@@ -387,6 +392,8 @@
(def ^:const local-pairing-action-pairing-account 2)
(def ^:const local-pairing-action-sync-device 3)
(def ^:const local-pairing-action-pairing-installation 4)
(def ^:const local-pairing-action-peer-discovery 5)
(def ^:const local-pairing-action-keystore-files-transfer 6)
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
@@ -503,6 +510,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 +558,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)
@@ -0,0 +1,9 @@
(ns status-im.contexts.centralized-metrics.effects
(:require
[native-module.core :as native-module]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/reg-fx :effects.centralized-metrics/toggle-metrics
(fn [enabled?]
(native-module/toggle-centralized-metrics enabled? #(log/debug "toggled-metrics" % enabled?))))
@@ -0,0 +1,33 @@
(ns status-im.contexts.centralized-metrics.events
(:require
[native-module.core :as native-module]
[re-frame.interceptor :as interceptor]
status-im.contexts.centralized-metrics.effects
[status-im.contexts.centralized-metrics.tracking :as tracking]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn push-event?
[db]
(or (not (:centralized-metrics/user-confirmed? db))
(:centralized-metrics/enabled? db)))
(defn centralized-metrics-interceptor
[context]
(when-let [event (tracking/tracked-event (interceptor/get-coeffect context :event))]
(log/debug "tracking event" event)
(when (push-event? (interceptor/get-coeffect context :db))
(native-module/add-centralized-metric event)))
context)
(def interceptor
(interceptor/->interceptor
:id :centralized-metrics
:after centralized-metrics-interceptor))
(rf/reg-event-fx :centralized-metrics/toggle-centralized-metrics
(fn [{:keys [db]} [enabled?]]
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
:db (assoc db
:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? enabled?)}))
@@ -0,0 +1,37 @@
(ns status-im.contexts.centralized-metrics.events-test
(:require
[cljs.test :refer-macros [deftest is testing]]
matcher-combinators.test
[status-im.contexts.centralized-metrics.events :as events]
[status-im.contexts.centralized-metrics.tracking :as tracking]
[test-helpers.unit :as h]))
(deftest push-event-test
(testing "returns correct boolean value"
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
(is (true? (events/push-event? {:centralized-metrics/enabled? true})))
(is (false? (events/push-event? {:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? false})))))
(deftest centralized-metrics-interceptor-test
(testing "processes context correctly"
(with-redefs [tracking/tracked-event (fn [_] {:metric "mocked-event"})
events/push-event? (fn [_] true)]
(let [context {:coeffects {:event [:some-event]
:db {:centralized-metrics/enabled? true}}}]
(is (= context (events/centralized-metrics-interceptor context)))))))
(h/deftest-event :centralized-metrics/toggle-centralized-metrics
[event-id dispatch]
(testing "toggling value to true"
(let [enabled? true
expected-fxs {:db {:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? enabled?}
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
(is (match? expected-fxs (dispatch [event-id enabled?])))))
(testing "toggling value to false"
(let [enabled? false
expected-fxs {:db {:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? enabled?}
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
(is (match? expected-fxs (dispatch [event-id enabled?]))))))
@@ -0,0 +1,40 @@
(ns status-im.contexts.centralized-metrics.tracking
(:require
[legacy.status-im.utils.build :as build]
[react-native.platform :as platform]))
(defn user-journey-event
[action]
{:metric
{:eventName "user-journey"
:platform platform/os
:appVersion build/app-short-version
:eventValue {:action action}}})
(def ^:const app-started-event "app-started")
(def ^:const navigate-to-create-profile-event "navigate-to-create-profile")
(def ^:const communities-tab-clicked "communities-tab-clicked")
(def ^:const wallet-tab-clicked "wallet-tab-clicked")
(def ^:const chats-tab-clicked "chats-tab-clicked")
(defn track-view-id-event
[view-id]
(case view-id
:communities-stack (user-journey-event communities-tab-clicked)
:chats-stack (user-journey-event chats-tab-clicked)
:wallet-stack (user-journey-event wallet-tab-clicked)
nil))
(defn tracked-event
[[event-name second-parameter]]
(case event-name
:onboarding/navigate-to-create-profile
(user-journey-event navigate-to-create-profile-event)
:profile/get-profiles-overview-success
(user-journey-event app-started-event)
:set-view-id
(track-view-id-event second-parameter)
nil))
@@ -0,0 +1,35 @@
(ns status-im.contexts.centralized-metrics.tracking-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[legacy.status-im.utils.build :as build]
[react-native.platform :as platform]
[status-im.contexts.centralized-metrics.tracking :as tracking]))
(deftest user-journey-event-test
(testing "creates correct metric event"
(let [action "some-action"
expected {:metric {:eventName "user-journey"
:platform platform/os
:appVersion build/app-short-version
:eventValue {:action action}}}]
(is (= expected (tracking/user-journey-event action))))))
(deftest track-view-id-event-test
(testing "returns correct event for view-id"
(is (= (tracking/user-journey-event tracking/communities-tab-clicked)
(tracking/track-view-id-event :communities-stack)))
(is (= (tracking/user-journey-event tracking/chats-tab-clicked)
(tracking/track-view-id-event :chats-stack)))
(is (= (tracking/user-journey-event tracking/wallet-tab-clicked)
(tracking/track-view-id-event :wallet-stack)))
(is (nil? (tracking/track-view-id-event :unknown-stack)))))
(deftest tracked-event-test
(testing "returns correct event for given inputs"
(is (= (tracking/user-journey-event tracking/navigate-to-create-profile-event)
(tracking/tracked-event [:onboarding/navigate-to-create-profile])))
(is (= (tracking/user-journey-event tracking/app-started-event)
(tracking/tracked-event [:profile/get-profiles-overview-success])))
(is (= (tracking/track-view-id-event :wallet-stack)
(tracking/tracked-event [:set-view-id :wallet-stack])))
(is (nil? (tracking/tracked-event [:unknown-event])))))
@@ -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]]))
@@ -139,6 +139,7 @@
[id token-gated? intro-message]
[[(when-not token-gated? (view-members id))
(when-not token-gated? (view-rules id intro-message))
(mark-as-read id)
(invite-contacts id)
(when token-gated? (view-token-gating id))
(show-qr id)
@@ -8,6 +8,7 @@
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.scroll-page.view :as scroll-page]
[status-im.config :as config]
[status-im.contexts.communities.actions.community-options.view :as options]
[status-im.contexts.communities.discover.style :as style]
[status-im.feature-flags :as ff]
@@ -76,12 +77,14 @@
:data [{:id :all
:label (i18n/label :t/all)
:accessibility-label :all-communities-tab}
{:id :open
:label (i18n/label :t/open)
:accessibility-label :open-communities-tab}
{:id :gated
:label (i18n/label :t/gated)
:accessibility-label :gated-communities-tab}]}]])
(when config/show-not-implemented-features?
{:id :open
:label (i18n/label :t/open)
:accessibility-label :open-communities-tab})
(when config/show-not-implemented-features?
{:id :gated
:label (i18n/label :t/gated)
:accessibility-label :gated-communities-tab})]}]])
(defn loading-community-item
[_ _ _ {:keys [width]}]

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