Compare commits
48
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a9ad0ccea | ||
|
|
a8a08c82b0 | ||
|
|
aa28678188 | ||
|
|
67aa733736 | ||
|
|
cee21241d4 | ||
|
|
60ad7c8a29 | ||
|
|
4989c92780 | ||
|
|
c6a63e30b2 | ||
|
|
07005f8ad5 | ||
|
|
3ab345563c | ||
|
|
cef1308b3a | ||
|
|
4b8a612df4 | ||
|
|
e4639c153f | ||
|
|
8597b899bd | ||
|
|
a5c8182461 | ||
|
|
89bb3ea5c3 | ||
|
|
3bb7c308e3 | ||
|
|
1a4987478c | ||
|
|
540094c229 | ||
|
|
08b65cbcb7 | ||
|
|
d623cc8444 | ||
|
|
4b7c906df2 | ||
|
|
3b446963ef | ||
|
|
cec46f985a | ||
|
|
06b2996167 | ||
|
|
02e24208db | ||
|
|
84b8943fd4 | ||
|
|
c52b3e457e | ||
|
|
21cc8a199a | ||
|
|
59374543ef | ||
|
|
9f84a7b912 | ||
|
|
2b0847ef76 | ||
|
|
97b19c5440 | ||
|
|
b3e88508ac | ||
|
|
7b09402fcb | ||
|
|
a912125ba9 | ||
|
|
2d0437dd5e | ||
|
|
43651ef0d0 | ||
|
|
13232dc7b7 | ||
|
|
93b5f7a918 | ||
|
|
4898d32243 | ||
|
|
588692e0eb | ||
|
|
bd9e440839 | ||
|
|
940edc2e53 | ||
|
|
5a93cd755e | ||
|
|
942c130d23 | ||
|
|
bb8aad3be8 | ||
|
|
ba76b9fd51 |
@@ -74,7 +74,8 @@
|
|||||||
;; https://github.com/borkdude/clj-kondo/issues/867
|
;; https://github.com/borkdude/clj-kondo/issues/867
|
||||||
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
|
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
|
||||||
number
|
number
|
||||||
legacy.status-im.test-helpers/restore-app-db]}
|
legacy.status-im.test-helpers/restore-app-db
|
||||||
|
(cljs.test/is [match-strict?])]}
|
||||||
:unresolved-var {:level :error}
|
:unresolved-var {:level :error}
|
||||||
:unsorted-required-namespaces {:level :error}
|
:unsorted-required-namespaces {:level :error}
|
||||||
:unused-alias {:level :warning}
|
:unused-alias {:level :warning}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ DEFAULT_NETWORK=mainnet_rpc
|
|||||||
DEV_BUILD=1
|
DEV_BUILD=1
|
||||||
ETHEREUM_DEV_CLUSTER=1
|
ETHEREUM_DEV_CLUSTER=1
|
||||||
EXTENSIONS=0
|
EXTENSIONS=0
|
||||||
FLEET=status.prod
|
|
||||||
GROUP_CHATS_ENABLED=1
|
GROUP_CHATS_ENABLED=1
|
||||||
LOG_LEVEL=info
|
LOG_LEVEL=info
|
||||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ DEBUG_WEBVIEW=1
|
|||||||
DEFAULT_NETWORK=goerli_rpc
|
DEFAULT_NETWORK=goerli_rpc
|
||||||
ETHEREUM_DEV_CLUSTER=1
|
ETHEREUM_DEV_CLUSTER=1
|
||||||
EXTENSIONS=0
|
EXTENSIONS=0
|
||||||
FLEET=status.prod
|
FLEET=status.staging
|
||||||
GROUP_CHATS_ENABLED=1
|
GROUP_CHATS_ENABLED=1
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
MAILSERVER_CONFIRMATIONS_ENABLED=0
|
MAILSERVER_CONFIRMATIONS_ENABLED=0
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ DEBUG_WEBVIEW=1
|
|||||||
DEFAULT_NETWORK=goerli_rpc
|
DEFAULT_NETWORK=goerli_rpc
|
||||||
ETHEREUM_DEV_CLUSTER=1
|
ETHEREUM_DEV_CLUSTER=1
|
||||||
EXTENSIONS=0
|
EXTENSIONS=0
|
||||||
FLEET=status.prod
|
|
||||||
GROUP_CHATS_ENABLED=1
|
GROUP_CHATS_ENABLED=1
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ DEBUG_WEBVIEW=1
|
|||||||
DEFAULT_NETWORK=mainnet_rpc
|
DEFAULT_NETWORK=mainnet_rpc
|
||||||
ETHEREUM_DEV_CLUSTER=1
|
ETHEREUM_DEV_CLUSTER=1
|
||||||
EXTENSIONS=0
|
EXTENSIONS=0
|
||||||
FLEET=status.prod
|
|
||||||
GROUP_CHATS_ENABLED=1
|
GROUP_CHATS_ENABLED=1
|
||||||
LOG_LEVEL=info
|
LOG_LEVEL=info
|
||||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ DEBUG_WEBVIEW=0
|
|||||||
DEFAULT_NETWORK=mainnet_rpc
|
DEFAULT_NETWORK=mainnet_rpc
|
||||||
ETHEREUM_DEV_CLUSTER=0
|
ETHEREUM_DEV_CLUSTER=0
|
||||||
EXTENSIONS=0
|
EXTENSIONS=0
|
||||||
FLEET=status.prod
|
|
||||||
GROUP_CHATS_ENABLED=1
|
GROUP_CHATS_ENABLED=1
|
||||||
LOG_LEVEL=
|
LOG_LEVEL=
|
||||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|||||||
+14
-9
@@ -1,10 +1,15 @@
|
|||||||
*
|
/*
|
||||||
|
|
||||||
|
# Format top-level js files.
|
||||||
!*.js
|
!*.js
|
||||||
!*/
|
|
||||||
*.clj-kondo
|
# Ignore all except src/js/**/*.js
|
||||||
*.shadow-cljs
|
!/src/
|
||||||
modules
|
/src/*
|
||||||
result
|
!/src/js
|
||||||
target
|
!/src/js/**/*.js
|
||||||
component-spec
|
|
||||||
/app
|
# Ignore all except translations/en.json
|
||||||
|
!/translations/
|
||||||
|
/translations/*
|
||||||
|
!/translations/en.json
|
||||||
|
|||||||
@@ -6,4 +6,8 @@ module.exports = {
|
|||||||
tabWidth: 2,
|
tabWidth: 2,
|
||||||
trailingComma: 'all',
|
trailingComma: 'all',
|
||||||
useTabs: false,
|
useTabs: false,
|
||||||
|
|
||||||
|
// JSON sorting
|
||||||
|
jsonSortOrder: '{ "/.*/": "caseInsensitiveLexical" } ',
|
||||||
|
plugins: ['prettier-plugin-sort-json'],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ lint: ##@test Run code style checks
|
|||||||
scripts/lint/translations.clj && \
|
scripts/lint/translations.clj && \
|
||||||
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
|
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
|
||||||
sh scripts/lint/trailing-newline.sh && \
|
sh scripts/lint/trailing-newline.sh && \
|
||||||
node_modules/.bin/prettier --write .
|
node_modules/.bin/prettier --check .
|
||||||
|
|
||||||
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
|
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
|
||||||
lint-fix: export TARGET := clojure
|
lint-fix: export TARGET := clojure
|
||||||
@@ -353,13 +353,17 @@ test: export SHADOW_NS_REGEXP := .*-test$$
|
|||||||
test: ##@test Run all Clojure tests
|
test: ##@test Run all Clojure tests
|
||||||
test: _test-clojure
|
test: _test-clojure
|
||||||
|
|
||||||
|
# Note: we need to override the :output-to and :ns-regexp options because
|
||||||
|
# shadow-cljs has a bug where it will not read from the env vars to expand the
|
||||||
|
# configuration when the shadow-cljs mobile target is already running.
|
||||||
test-watch-for-repl: export TARGET := default
|
test-watch-for-repl: export TARGET := default
|
||||||
test-watch-for-repl: export SHADOW_OUTPUT_TO := target/test/test.js
|
test-watch-for-repl: export SHADOW_OUTPUT_TO := target/test/test.js
|
||||||
test-watch-for-repl: export SHADOW_NS_REGEXP := .*-test$$
|
test-watch-for-repl: export SHADOW_NS_REGEXP := .*-test$$
|
||||||
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
|
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
|
||||||
|
rm -f "$$SHADOW_OUTPUT_TO" && \
|
||||||
yarn install && shadow-cljs compile mocks && \
|
yarn install && shadow-cljs compile mocks && \
|
||||||
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
|
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
|
||||||
'yarn shadow-cljs watch test --verbose' \
|
"yarn shadow-cljs watch test --verbose --config-merge '{:output-to \"$(SHADOW_OUTPUT_TO)\" :ns-regexp \"$(SHADOW_NS_REGEXP)\"}'" \
|
||||||
"until [ -f $$SHADOW_OUTPUT_TO ] ; do sleep 1 ; done ; node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO --repl"
|
"until [ -f $$SHADOW_OUTPUT_TO ] ; do sleep 1 ; done ; node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO --repl"
|
||||||
|
|
||||||
test-unit: export SHADOW_OUTPUT_TO := target/unit_test/test.js
|
test-unit: export SHADOW_OUTPUT_TO := target/unit_test/test.js
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ pipeline {
|
|||||||
--rerun_count=2 \
|
--rerun_count=2 \
|
||||||
--testrail_report=True \
|
--testrail_report=True \
|
||||||
-m testrail_id \
|
-m testrail_id \
|
||||||
-m \"new_ui_critical or new_ui_medium\" \
|
-m \"nightly\" \
|
||||||
-k \"${params.KEYWORD_EXPRESSION}\" \
|
-k \"${params.KEYWORD_EXPRESSION}\" \
|
||||||
--apk=${params.APK_URL ?: apk_path}
|
--apk=${params.APK_URL ?: apk_path}
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -35,13 +35,11 @@ pipeline {
|
|||||||
description: 'OBSOLETE ARGUMENT TO BE REMOVED',
|
description: 'OBSOLETE ARGUMENT TO BE REMOVED',
|
||||||
defaultValue: 'DUMMY',
|
defaultValue: 'DUMMY',
|
||||||
)
|
)
|
||||||
/* Commented to use TEST_MARKERS values from job params
|
|
||||||
string(
|
string(
|
||||||
name: 'TEST_MARKERS',
|
name: 'TEST_MARKERS',
|
||||||
description: 'Marker expression for matching tests to run.',
|
description: 'Marker expression for matching tests to run.',
|
||||||
defaultValue: 'new_ui_critical',
|
defaultValue: 'smoke',
|
||||||
)
|
)
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options {
|
options {
|
||||||
|
|||||||
+27
-51
@@ -1,67 +1,43 @@
|
|||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
[Starting Guide](starting-guide.md)
|
|
||||||
|
|
||||||
[IDE Setup](ide-setup.md)
|
|
||||||
|
|
||||||
|
|
||||||
|
- [Starting Guide](starting-guide.md)
|
||||||
|
- [IDE Setup](ide-setup.md)
|
||||||
|
|
||||||
## Development Process
|
## Development Process
|
||||||
|
|
||||||
[Coding guidelines](new-guidelines.md)
|
- [Coding guidelines](new-guidelines.md)
|
||||||
|
- [UI components coding guidelines](ui-guidelines.md)
|
||||||
[UI components coding guidelines](ui-guidelines.md)
|
- [Release Checklist](release-checklist.md)
|
||||||
|
- [Release Guide](release-guide.md)
|
||||||
[Release Checklist](release-checklist.md)
|
- [Merging PR process](merging-pr-process.md)
|
||||||
|
- [PR Review Policy](pr-review-policy.md)
|
||||||
[Release Guide](release-guide.md)
|
- [Working on PR together with QA team](pipeline_process.md)
|
||||||
|
- [Debugging](debugging.md)
|
||||||
[Merging PR process](merging-pr-process.md)
|
- [Patching](patching.md)
|
||||||
|
- [Creating a pixel perfect UI](pixel-perfection.md)
|
||||||
[PR Review Policy](pr-review-policy.md)
|
- [Contributing to status-go](status-go-changes.md)
|
||||||
|
- [Malli schemas (recorded demo)](https://www.youtube.com/watch?v=SlRio70aYVI) ([slides](files/forging-code-with-schemas-sep-2023-slides.pdf))
|
||||||
[Working on PR together with QA team](pipeline_process.md)
|
|
||||||
|
|
||||||
[Debugging](debugging.md)
|
|
||||||
|
|
||||||
[Patching](patching.md)
|
|
||||||
|
|
||||||
[Creating a pixel perfect UI](pixel-perfection.md)
|
|
||||||
|
|
||||||
[Contributing to status-go](status-go-changes.md)
|
|
||||||
|
|
||||||
[Malli schemas (recorded demo)](https://www.youtube.com/watch?v=SlRio70aYVI) ([slides](files/forging-code-with-schemas-sep-2023-slides.pdf))
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
[How to run local tests](testing.md)
|
- [Overview](tests/tests-overview.md)
|
||||||
|
- [How to run local tests](tests/how-to-run-local-tests.md)
|
||||||
[End-to-end tests (e2e) overview](how-to-launch-e2e.md)
|
- [End-to-end tests (e2e) overview](tests/how-to-launch-e2e.md)
|
||||||
|
- [Component tests (jest) overview](tests/component-tests-overview.md)
|
||||||
[Component tests (jest) overview](component-tests-overview.md)
|
|
||||||
|
|
||||||
|
|
||||||
## Project details
|
## Project details
|
||||||
|
|
||||||
[status-go introduction (recorded meeting)](https://drive.google.com/file/d/1B7TljmTZ8fHkqJH8ChU1Cp4FGDFM03gq/view)
|
- [status-go introduction (recorded meeting)](https://drive.google.com/file/d/1B7TljmTZ8fHkqJH8ChU1Cp4FGDFM03gq/view)
|
||||||
|
- [re-frame usage (recorded meeting)](https://drive.google.com/file/d/1qv_E0CEGzQpu_zGXD0gCTU5EvhC2k8Jy/view)
|
||||||
[re-frame usage (recorded meeting)](https://drive.google.com/file/d/1qv_E0CEGzQpu_zGXD0gCTU5EvhC2k8Jy/view)
|
- [status app functionality demo](https://drive.google.com/file/u/0/d/1PmwsMLTLDNNIdv5_6wvMOwoj2PfT50c6/view)
|
||||||
|
|
||||||
[status app functionality demo](https://drive.google.com/file/u/0/d/1PmwsMLTLDNNIdv5_6wvMOwoj2PfT50c6/view)
|
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
[Importing icons from Figma into project](export-icons.md)
|
- [Importing icons from Figma into project](export-icons.md)
|
||||||
|
- [Updating Status APK builds for the F-Droid Android application catalogue](fdroid.md)
|
||||||
[Updating Status APK builds for the F-Droid Android application catalogue](fdroid.md)
|
- [Troubleshooting for known errors](troubleshooting.md)
|
||||||
|
|
||||||
[Troubleshooting for known errors](troubleshooting.md)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Outdated:
|
## Outdated:
|
||||||
|
|
||||||
[Old guidelines](codebase-structure-and-guidelines.md)
|
- [Old guidelines](codebase-structure-and-guidelines.md)
|
||||||
|
- [Post mortem analysis](post-mortem.md)
|
||||||
[Post mortem analysis](post-mortem.md)
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ Ready for testing, a PR should meet the following criteria:
|
|||||||
### E2E tests and analyzing the results
|
### E2E tests and analyzing the results
|
||||||
|
|
||||||
The PR **MUST** be moved to the E2E column when it is ready for testing (**mandatory for all PRs**).
|
The PR **MUST** be moved to the E2E column when it is ready for testing (**mandatory for all PRs**).
|
||||||
That will also trigger e2e tests run. QAs are monitoring PRs from E2E column and take it into test.
|
That will also trigger e2e tests run. QAs are monitoring PRs from E2E column and take it into test.
|
||||||
This step cannot be skipped. So, at least one comment from the `status-im-auto` bot with results is a prerequisite for moving forward.
|
This step cannot be skipped. So, at least one comment from the `status-im-auto` bot with results is a prerequisite for moving forward.
|
||||||
Information on how to analyze tests can be found [here](https://github.com/status-im/status-mobile/blob/develop/doc/how-to-launch-e2e.md).
|
Information on how to analyze tests can be found [here](https://github.com/status-im/status-mobile/blob/develop/doc/tests/how-to-launch-e2e.md).
|
||||||
Tests might be flaky, as they depend on infrastructure - SauceLabs and Waku.
|
Tests might be flaky, as they depend on infrastructure - SauceLabs and Waku.
|
||||||
|
|
||||||
If there are `Failed tests` and you are not sure about the reason, you can always ping the mobile QAs for help (preferably in PRs by `@status-im/mobile-qa`).
|
If there are `Failed tests` and you are not sure about the reason, you can always ping the mobile QAs for help (preferably in PRs by `@status-im/mobile-qa`).
|
||||||
@@ -46,14 +46,14 @@ Please, respect this rule.**
|
|||||||
|
|
||||||
### Adding `skip-manual-qa`
|
### Adding `skip-manual-qa`
|
||||||
|
|
||||||
**Do not hesitate to use a `skip-manual-qa`** if you're sure that it is a simple flow and you checked it.
|
**Do not hesitate to use a `skip-manual-qa`** if you're sure that it is a simple flow and you checked it.
|
||||||
- Please ask another team member before adding the `skip-manual-qa` label (PR/Status community/DMs) so that there's a second opinion.
|
- Please ask another team member before adding the `skip-manual-qa` label (PR/Status community/DMs) so that there's a second opinion.
|
||||||
- The PR MUST have a proper reasoning why manual QA is skipped.
|
- The PR MUST have a proper reasoning why manual QA is skipped.
|
||||||
- The PR MUST include the steps of testing that has been done by the developer prior to moving it forward.
|
- The PR MUST include the steps of testing that has been done by the developer prior to moving it forward.
|
||||||
|
|
||||||
**NOTE:** Make sure that QAs are OK with that;
|
**NOTE:** Make sure that QAs are OK with that;
|
||||||
|
|
||||||
Before merging PRs, please make sure that information is added about how you tested the PRs, that e2s have been passed and their results have been reviewed.
|
Before merging PRs, please make sure that information is added about how you tested the PRs, that e2s have been passed and their results have been reviewed.
|
||||||
|
|
||||||
The QA team appreciates your help!
|
The QA team appreciates your help!
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ The QA team appreciates your help!
|
|||||||
- QA engineer picks up one of PRs with the ```request-manual-qa``` label, drags the item to the ```IN TESTING``` column and assigns it to themselves.
|
- QA engineer picks up one of PRs with the ```request-manual-qa``` label, drags the item to the ```IN TESTING``` column and assigns it to themselves.
|
||||||
- During testing, QA will add comments describing the issues found, and also review automation tests results.
|
- During testing, QA will add comments describing the issues found, and also review automation tests results.
|
||||||
Usually found issues are numbered as "Issue 1, Issue 2", etc.
|
Usually found issues are numbered as "Issue 1, Issue 2", etc.
|
||||||
When the first round of testing is completed and all issues for this stage are found, the QA can add the ```Tested - Issues``` label and drag the card to the ```CONTRIBUTOR``` column. These two actions are optional.
|
When the first round of testing is completed and all issues for this stage are found, the QA can add the ```Tested - Issues``` label and drag the card to the ```CONTRIBUTOR``` column. These two actions are optional.
|
||||||
|
|
||||||
**IMPORTANT NOTE:** when the issues are fixed, developer **MUST** notify the QA that it is ready to be re-tested again by mention them in the PR.
|
**IMPORTANT NOTE:** when the issues are fixed, developer **MUST** notify the QA that it is ready to be re-tested again by mention them in the PR.
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ After that the developer merges PR into develop.
|
|||||||
_**How do I know if a design review is needed?**_
|
_**How do I know if a design review is needed?**_
|
||||||
|
|
||||||
There are three cases here depending on the changes in the PR:
|
There are three cases here depending on the changes in the PR:
|
||||||
1. **Functional PRs with UI changes:** after the ```Tested - OK``` label is added, the QA moves the PR to the ```Design review``` column + mentions ```@Francesca-G``` in comments.
|
1. **Functional PRs with UI changes:** after the ```Tested - OK``` label is added, the QA moves the PR to the ```Design review``` column + mentions ```@Francesca-G``` in comments.
|
||||||
2. **Component PRs:** once the PR has received a review from developers and e2e tests results, it can be moved directly to the ```Design review``` column by the developer (manual testing step can be skipped) + the developer mentions ```@Francesca-G``` in comments.
|
2. **Component PRs:** once the PR has received a review from developers and e2e tests results, it can be moved directly to the ```Design review``` column by the developer (manual testing step can be skipped) + the developer mentions ```@Francesca-G``` in comments.
|
||||||
3. **Functional PRs changes in which are not related to UI (e.g. a crash fix):** skip the ```Design review``` step (the PR should only be manually tested by QA).
|
3. **Functional PRs changes in which are not related to UI (e.g. a crash fix):** skip the ```Design review``` step (the PR should only be manually tested by QA).
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ There are three possible scenarios when the design review is completed:
|
|||||||
**Notes:**
|
**Notes:**
|
||||||
- If your PR has a long story and started from `develop` branch several days ago, please rebase it to current develop before adding label
|
- If your PR has a long story and started from `develop` branch several days ago, please rebase it to current develop before adding label
|
||||||
- if PR can be tested by developer (in case of small changes) and/or developer is sure that the changes made cannot introduce a regression, then PR can be merged without manual testing. Also, currently, PRs are not manually tested if the changes relate only the design (creation of components, etc.) and do not affect the functionality (see `skip-manual-qa` label)
|
- if PR can be tested by developer (in case of small changes) and/or developer is sure that the changes made cannot introduce a regression, then PR can be merged without manual testing. Also, currently, PRs are not manually tested if the changes relate only the design (creation of components, etc.) and do not affect the functionality (see `skip-manual-qa` label)
|
||||||
---
|
---
|
||||||
|
|
||||||
#### Why my PR is in `Contributor` column?
|
#### Why my PR is in `Contributor` column?
|
||||||
PR can be moved to this column by the ```status-github-bot``` or by QA engineer with label `Tested-issues` or if one of the requirements for manual QA was not met.
|
PR can be moved to this column by the ```status-github-bot``` or by QA engineer with label `Tested-issues` or if one of the requirements for manual QA was not met.
|
||||||
@@ -120,6 +120,6 @@ In the second case - after fixing of all found issues, the developer should ping
|
|||||||
6. In case of manual testing - the label ```Tested - OK``` from QA
|
6. In case of manual testing - the label ```Tested - OK``` from QA
|
||||||
7. In case of design review - the approval from the designer
|
7. In case of design review - the approval from the designer
|
||||||
|
|
||||||
You can merge your PR into develop - some useful clues you can find [here](https://notes.status.im/setup-e2e#3-Merging-PR)
|
You can merge your PR into develop - some useful clues you can find [here](https://notes.status.im/setup-e2e#3-Merging-PR)
|
||||||
|
|
||||||
HAPPY DEVELOPMENT! :tada:
|
HAPPY DEVELOPMENT! :tada:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ As a part of CI for Status mobile app and in order to ensure there are no regres
|
|||||||
- Automated tests written on Python 3.9 and pytest.
|
- Automated tests written on Python 3.9 and pytest.
|
||||||
- Appium (server) and Selenium WebDriver (protocol) are the base of test automation framework.
|
- Appium (server) and Selenium WebDriver (protocol) are the base of test automation framework.
|
||||||
|
|
||||||
TestRail is a test case management system tool where we have test cases.
|
TestRail is a test case management system tool where we have test cases.
|
||||||
|
|
||||||
|
|
||||||
Each of the test case gets a priority (Critical/High/Medium)
|
Each of the test case gets a priority (Critical/High/Medium)
|
||||||
@@ -20,21 +20,21 @@ For now we support e2e for Android only.
|
|||||||
Whenever we need to push set of test scripts we create 16 parallel sessions (max, but depending on amount of cases that are included in job) and each thread: 1) uploads Android .apk file to SauceLabs -> 2) runs through the test steps -> 3) receives results whether test failed on particular step or succeeded with no errors -> 3) Parse test results and push them as a Github comment (if the suite ran against respective PR) and into TestRail.
|
Whenever we need to push set of test scripts we create 16 parallel sessions (max, but depending on amount of cases that are included in job) and each thread: 1) uploads Android .apk file to SauceLabs -> 2) runs through the test steps -> 3) receives results whether test failed on particular step or succeeded with no errors -> 3) Parse test results and push them as a Github comment (if the suite ran against respective PR) and into TestRail.
|
||||||
|
|
||||||
We push **whole automation test suite (currently 155, amount is changing)** against each nightly build (if the nightly builds job succeeded). Results of the test run are saved in TestRail.
|
We push **whole automation test suite (currently 155, amount is changing)** against each nightly build (if the nightly builds job succeeded). Results of the test run are saved in TestRail.
|
||||||
And also we push set of autotests whenever PR with successful builds got moved in to `E2E Tests` column from [Pipeline for QA dashboard ](https://github.com/status-im/status-react/projects/7).
|
And also we push set of autotests whenever PR with successful builds got moved in to `E2E Tests` column from [Pipeline for QA dashboard ](https://github.com/status-im/status-react/projects/7).
|
||||||
In that case we save results in TestRail as well and push a comment with test results in a respective PR.
|
In that case we save results in TestRail as well and push a comment with test results in a respective PR.
|
||||||
|
|
||||||
For example: https://github.com/status-im/status-react/pull/9147#issuecomment-540008770
|
For example: https://github.com/status-im/status-react/pull/9147#issuecomment-540008770
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
The test_send_stt_from_wallet opens link in TestRail https://ethstatus.testrail.net/index.php?/tests/view/890885 where performed steps could be found
|
The test_send_stt_from_wallet opens link in TestRail https://ethstatus.testrail.net/index.php?/tests/view/890885 where performed steps could be found
|
||||||
List of all runs performed by test jobs could be found here https://ethstatus.testrail.net/index.php?/runs/overview/14
|
List of all runs performed by test jobs could be found here https://ethstatus.testrail.net/index.php?/runs/overview/14
|
||||||
|
|
||||||
**For credentials for TestRail to see results ping Chu in DM**:
|
**For credentials for TestRail to see results ping Chu in DM**:
|
||||||
|
|
||||||
Opening any test run navigates you to list of test cases with results:
|
Opening any test run navigates you to list of test cases with results:
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## What about launching e2e manually
|
## What about launching e2e manually
|
||||||
@@ -53,12 +53,12 @@ Params to specify:
|
|||||||
- test_marks: tests by priorities (by default: `critical or high or medium`, which corresponds the whole suite; to launch the same suite as in PRs, use `critical or high`)
|
- test_marks: tests by priorities (by default: `critical or high or medium`, which corresponds the whole suite; to launch the same suite as in PRs, use `critical or high`)
|
||||||
- testrail_case_id: here is the list of test cases which you may find in test rail (4-digit value)
|
- testrail_case_id: here is the list of test cases which you may find in test rail (4-digit value)
|
||||||
|
|
||||||
For easier access you can hit `Rerun tests` in GH comment and testrail_case_id/ apk_name/ pr_id will be filled automatically. For making sure that tests are being rerun on most recent e2e build it is recommended to paste link to the last e2e build in apk_name field. The list of PR builds can be found in Jenkins Builds block on PR page.
|
For easier access you can hit `Rerun tests` in GH comment and testrail_case_id/ apk_name/ pr_id will be filled automatically. For making sure that tests are being rerun on most recent e2e build it is recommended to paste link to the last e2e build in apk_name field. The list of PR builds can be found in Jenkins Builds block on PR page.
|
||||||

|

|
||||||
And then hit ‘Build’.
|
And then hit ‘Build’.
|
||||||
Once the job starts it picks up specified tests, runs them against provided apk and sends results to pull request.
|
Once the job starts it picks up specified tests, runs them against provided apk and sends results to pull request.
|
||||||
|
|
||||||
Even we have 16 parallel sessions for testing it’s a time consuming operation (whole test suite we have automated at the moment takes ~140 minutes to finish).
|
Even we have 16 parallel sessions for testing it’s a time consuming operation (whole test suite we have automated at the moment takes ~140 minutes to finish).
|
||||||
So for PRs we pick only set of `critical or high` (you can also use this in TEST_MARKS param for job)
|
So for PRs we pick only set of `critical or high` (you can also use this in TEST_MARKS param for job)
|
||||||
tests (otherwise some PRs could wait their turn of the scheduled Jenkins job till the next day).
|
tests (otherwise some PRs could wait their turn of the scheduled Jenkins job till the next day).
|
||||||
|
|
||||||
@@ -78,9 +78,9 @@ Several examples of when test fails to succeed:
|
|||||||
|
|
||||||
- **Valid issue in the automated test scripts** - that's what we're looking for
|
- **Valid issue in the automated test scripts** - that's what we're looking for
|
||||||
|
|
||||||
Example: here is the test results https://github.com/status-im/status-react/pull/13015#issuecomment-1016495043 where one test failed.
|
Example: here is the test results https://github.com/status-im/status-react/pull/13015#issuecomment-1016495043 where one test failed.
|
||||||
1. Open the test in TestRail and open session recorded for this test in SauceLabs
|
1. Open the test in TestRail and open session recorded for this test in SauceLabs
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
In TestRail you may find all the steps performed by the test.
|
In TestRail you may find all the steps performed by the test.
|
||||||
@@ -98,6 +98,6 @@ Not all features of the app could be covered by e2e at the moment:
|
|||||||
## Brief flow for test to be automated
|
## Brief flow for test to be automated
|
||||||
|
|
||||||
Whenever there is a need to have a new test:
|
Whenever there is a need to have a new test:
|
||||||
1) Create a test scenario in TestRail.
|
1) Create a test scenario in TestRail.
|
||||||
2) If certain item could be checked in scope of existing test case we update existing one (otherwise we may have thousands of test cases which is overkill to manage in TestRail as well as in automated test scripts). And also complex autotests increase probability to not catch regressions by stopping test execution (due to valid bug or changed feature) keeping the rest test steps uncovered. So here we need to balance when it makes sense to update existing test case with more checks.
|
2) If certain item could be checked in scope of existing test case we update existing one (otherwise we may have thousands of test cases which is overkill to manage in TestRail as well as in automated test scripts). And also complex autotests increase probability to not catch regressions by stopping test execution (due to valid bug or changed feature) keeping the rest test steps uncovered. So here we need to balance when it makes sense to update existing test case with more checks.
|
||||||
3) Then we create test script based on the test case, ensure test passes for the build and pushing the changes to repo.
|
3) Then we create test script based on the test case, ensure test passes for the build and pushing the changes to repo.
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
# Tests
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This document provides a general overview of the types of tests we use and when
|
||||||
|
to use them. It is not meant to be a tutorial or a detailed documentation about
|
||||||
|
testing in software development.
|
||||||
|
|
||||||
|
## Types of tests
|
||||||
|
|
||||||
|
Tests in `status-mobile` are comprised of:
|
||||||
|
|
||||||
|
- Unit tests
|
||||||
|
- Subscription tests
|
||||||
|
- Event tests
|
||||||
|
- Tests for various utilities
|
||||||
|
- [Component tests](./component-tests-overview.md)
|
||||||
|
- Integration/contract tests
|
||||||
|
- [End-to-end tests](./how-to-launch-e2e.md)
|
||||||
|
|
||||||
|
We apply the [test
|
||||||
|
pyramid](https://en.wikipedia.org/wiki/Test_automation#Testing_at_different_levels)
|
||||||
|
strategy, which means we want the majority of tests at the bottom of the
|
||||||
|
pyramid. Those should be fast and deterministic and support REPL-Driven
|
||||||
|
development (RDD). Slightly above them, we have component tests, then
|
||||||
|
integration/contract tests and finally end-to-end tests. The closer to the top
|
||||||
|
of the pyramid, the more valuable a test can be, but also more difficult to
|
||||||
|
pinpoint why it failed and harder to make it dependable.
|
||||||
|
|
||||||
|
*Note*: there are literally dozens of [types of
|
||||||
|
tests](https://en.wikipedia.org/wiki/Software_testing), each with its strengths
|
||||||
|
and weaknesses.
|
||||||
|
|
||||||
|
We tend not to stub or mock implementations in our tests, which means our tests
|
||||||
|
are [sociable](https://martinfowler.com/bliki/UnitTest.html).
|
||||||
|
|
||||||
|
## What to test?
|
||||||
|
|
||||||
|
The UI is driven by global & local state changes caused by events. Global state
|
||||||
|
is managed by re-frame and local state by Reagent atoms or React hooks. Except
|
||||||
|
for component and end-to-end tests, we test only non-UI code in `status-mobile`.
|
||||||
|
Given that the UI is greatly derived from global state, by guaranteeing the
|
||||||
|
state is correct we can prevent bugs and, more importantly, reduce the [cost of
|
||||||
|
change](https://www.pmi.org/disciplined-agile/agile/costofchange).
|
||||||
|
|
||||||
|
We strive to minimize the amount of _business logic_ in views (UI code). We
|
||||||
|
achieve this by moving capabilities to status-go and also by adhering to
|
||||||
|
re-frame's architecture.
|
||||||
|
|
||||||
|
Whenever appropriate (see section `When to test?`), we _may_ test:
|
||||||
|
|
||||||
|
- Re-frame events.
|
||||||
|
- Re-frame subscriptions.
|
||||||
|
- Utility functions.
|
||||||
|
- User journeys through integration/contract tests.
|
||||||
|
|
||||||
|
Interestingly, we don't test re-frame _effects_ in isolation.
|
||||||
|
|
||||||
|
### What are status-mobile integration and contract tests?
|
||||||
|
|
||||||
|
The mobile _integration tests_ can be used to "simulate" user interactions and
|
||||||
|
make actual calls to status-go via the RPC layer and actually receive signals.
|
||||||
|
We can also use these tests to verify the app-db and multiple subscriptions are
|
||||||
|
correct. We use the word _simulate_ because there is no UI. Basically, any flow
|
||||||
|
that can be driven by re-frame events is possible to automatically test. There
|
||||||
|
is no way to change or inspect local state managed by React.
|
||||||
|
|
||||||
|
A _contract test_ has the same capabilities as an integration test, but we want
|
||||||
|
to draw the line that they should focus more on a particupar RPC endpoint or
|
||||||
|
signal, and not on a user journey (e.g. create a wallet account). In the future,
|
||||||
|
we may consider running them automatically in status-go.
|
||||||
|
|
||||||
|
**Note:** integration tests and contract tests are currently overlapping in
|
||||||
|
their responsibilities and still require a clearer distinction.
|
||||||
|
|
||||||
|
## When to test?
|
||||||
|
|
||||||
|
(Automated) tests basically exist to support rapid software changes, but not
|
||||||
|
every piece of code should be tested. The following are general recommendations,
|
||||||
|
not rules.
|
||||||
|
|
||||||
|
- What would be the consequences to the user of a bug in the implementation you
|
||||||
|
are working on?
|
||||||
|
- Can a QA exercise all the branches in the code you changed? Not surprisingly,
|
||||||
|
usually QAs can't test many code paths (it may be nearly impossible), and
|
||||||
|
because PRs are not often tested by reviewers, many PRs can get into `develop`
|
||||||
|
without the necessary quality assurance.
|
||||||
|
- How costly was it for you to verify a function/event/etc was correct? Now
|
||||||
|
consider that this cost will be dispersed to every developer who needs to
|
||||||
|
change the implementation if there are no tests.
|
||||||
|
- Check the number of conditionals, and if they nest as well. Every conditional
|
||||||
|
may require two different assertions, and the number of assertions can grow
|
||||||
|
exponentially.
|
||||||
|
- How complicated are the arguments to the function? If they contain nested maps
|
||||||
|
or data that went through a few transformations, it may be tricky to decipher
|
||||||
|
what they are, unless you are familiar with the code. A test would be able to
|
||||||
|
capture the data, however complex they are.
|
||||||
|
|
||||||
|
### When to unit-test subscriptions?
|
||||||
|
|
||||||
|
Only test [layer-3
|
||||||
|
subscriptions](https://day8.github.io/re-frame/subscriptions/#the-four-layers),
|
||||||
|
i.e. don't bother testing extractor subscriptions (check the related
|
||||||
|
[guideline](https://github.com/status-im/status-mobile/blob/7774c4eac16fdee950a17bf5d07630c45a980f41/doc/new-guidelines.md#subscription-tests)).
|
||||||
|
Some layer-3 subscriptions can still be straightforward and may not be worth
|
||||||
|
testing.
|
||||||
|
|
||||||
|
- Check the number of _inputs_ to the sub (from the graph). The higher this
|
||||||
|
number, the greater the chance the subscription can break if any of the
|
||||||
|
input's implementation changes.
|
||||||
|
|
||||||
|
**Note**: if a tested subscription changes inadvertently, even if its own tests
|
||||||
|
still pass, other subscriptions that depend on it and have tests may still fail.
|
||||||
|
This is why we don't directly test the subscription handler, but instead, use
|
||||||
|
the macro `test-helpers.unit/deftest-sub`.
|
||||||
|
|
||||||
|
### When to unit-test events?
|
||||||
|
|
||||||
|
A good hint is to ask if you and other CCs need to rely on re-frisk, UI, REPL,
|
||||||
|
or FlowStorm to understand the event. If the answer is yes or probably, then a
|
||||||
|
test would be prudent.
|
||||||
|
|
||||||
|
- Many events only receive arguments and pass them along without much or any
|
||||||
|
transformation to an RPC call. These are straightforward and usually don't
|
||||||
|
need tests ([example](https://github.com/status-im/status-mobile/blob/7774c4eac16fdee950a17bf5d07630c45a980f41/src/status_im/contexts/contact/blocking/events.cljs#L79-L85)).
|
||||||
|
- Overall, every event basically returns two effects at most, `:fx` and/or
|
||||||
|
`:db`. Usually, the complicated part lies in the computation to return the new
|
||||||
|
app-db. If the event doesn't perform transformations in the app-db or just
|
||||||
|
does a trivial `assoc`, for example, it may not be worth testing.
|
||||||
|
|
||||||
|
For reference, the re-frame author particularly [suggests testing events and
|
||||||
|
subscriptions](https://github.com/day8/re-frame/blob/09e2d7132c479aa43f2a64164e54e42bf8511902/docs/Testing.md#what-to-test).
|
||||||
|
|
||||||
|
### When to unit-test utility functions?
|
||||||
|
|
||||||
|
Most utility functions in `status-mobile` are pure and can be readily and
|
||||||
|
cheaply tested.
|
||||||
|
|
||||||
|
- If the utility is used in an event/subscription and if the event/subscription
|
||||||
|
has tests, you may prefer to test the event/subscription and not the utility,
|
||||||
|
or the other way around sometimes.
|
||||||
|
- If the utility is tricky to verify, such as functions manipulating time, write
|
||||||
|
tests ([example](https://github.com/status-im/status-mobile/blob/7774c4eac16fdee950a17bf5d07630c45a980f41/src/utils/datetime.cljs#L1)).
|
||||||
|
- Utilities can be particularly hard to verify by QAs because they can be lower
|
||||||
|
level and require very particular inputs. In such cases, consider writing
|
||||||
|
tests.
|
||||||
|
|
||||||
|
### When to write integration/contract tests?
|
||||||
|
|
||||||
|
- You want to make real calls to status-go because you think the unit tests are
|
||||||
|
not enough (test pyramid strategy).
|
||||||
|
- You constantly need to retest the same things on the UI, sometimes over
|
||||||
|
multiple screens.
|
||||||
|
- The flow is too important to rely only on manual QA, which can't always be
|
||||||
|
done due to resource limits, so an integration/contract test fills this gap.
|
||||||
|
- You want to rely less on end-to-end tests, which can be more unreliable and
|
||||||
|
slower to change.
|
||||||
|
- You want automatic verifications for some area of the mobile app whenever
|
||||||
|
status-go is upgraded.
|
||||||
|
|
||||||
|
**Note**: the feedback cycle to write integration tests is longer than unit
|
||||||
|
tests because they are slower and harder to debug. Using the REPL with them is
|
||||||
|
difficult due to their stateful nature.
|
||||||
|
|
||||||
|
### When to test Quo components?
|
||||||
|
|
||||||
|
This is covered in [quo/README.md#component-tests](https://github.com/status-im/status-mobile/blob/7774c4eac16fdee950a17bf5d07630c45a980f41/src/quo/README.md#component-tests).
|
||||||
+2
-2
@@ -915,7 +915,7 @@ PODS:
|
|||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2022.05.16.00)
|
- RCT-Folly (= 2022.05.16.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-compat (2.12.2):
|
- react-native-compat (2.11.2):
|
||||||
- glog
|
- glog
|
||||||
- RCT-Folly (= 2022.05.16.00)
|
- RCT-Folly (= 2022.05.16.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
@@ -1517,7 +1517,7 @@ SPEC CHECKSUMS:
|
|||||||
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
|
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
|
||||||
react-native-blur: 799045500f56146afc46245148080e7b7623cb75
|
react-native-blur: 799045500f56146afc46245148080e7b7623cb75
|
||||||
react-native-cameraroll: af8eec1e585d053ff485d98ec837f9a8a11b5745
|
react-native-cameraroll: af8eec1e585d053ff485d98ec837f9a8a11b5745
|
||||||
react-native-compat: 84e00e8dcff9251278c0d48f2bce81f4502e3925
|
react-native-compat: 3af9add14d349701306d3d052638435f6795ac2c
|
||||||
react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727
|
react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727
|
||||||
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
|
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
|
||||||
react-native-hole-view: 6935448993bac79f2b5a4ad7e9741094cf810679
|
react-native-hole-view: 6935448993bac79f2b5a4ad7e9741094cf810679
|
||||||
|
|||||||
@@ -711,11 +711,11 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8",
|
"path": "nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1",
|
||||||
"host": "https://repo.clojars.org",
|
"host": "https://repo.clojars.org",
|
||||||
"jar": {
|
"jar": {
|
||||||
"sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd",
|
"sha1": "f0830a112cae8ee931a90d9f39214a0ed4d44150",
|
||||||
"sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl"
|
"sha256": "1rjcgqhms84xmnhs7sqcd3b2dpa37mmzgz2yz33yz2rdb9skl96g"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
|
|||||||
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
|
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
|
||||||
nrepl/bencode/1.1.0/bencode-1.1.0.jar
|
nrepl/bencode/1.1.0/bencode-1.1.0.jar
|
||||||
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
|
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
|
||||||
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar
|
nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1.jar
|
||||||
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
|
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
|
||||||
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
|
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
|
||||||
org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
|
org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
|
||||||
|
|||||||
+2
-1
@@ -97,7 +97,8 @@
|
|||||||
"jest-silent-reporter": "^0.5.0",
|
"jest-silent-reporter": "^0.5.0",
|
||||||
"nodemon": "^2.0.16",
|
"nodemon": "^2.0.16",
|
||||||
"nyc": "^14.1.1",
|
"nyc": "^14.1.1",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^3.3.3",
|
||||||
|
"prettier-plugin-sort-json": "^4.0.0",
|
||||||
"process": "0.11.10",
|
"process": "0.11.10",
|
||||||
"react-test-renderer": "18.1.0",
|
"react-test-renderer": "18.1.0",
|
||||||
"shadow-cljs": "2.26.2",
|
"shadow-cljs": "2.26.2",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
[cider/piggieback "0.4.1"]
|
[cider/piggieback "0.4.1"]
|
||||||
[org.slf4j/slf4j-nop "2.0.9"]
|
[org.slf4j/slf4j-nop "2.0.9"]
|
||||||
[re-frisk-remote "1.6.0"]
|
[re-frisk-remote "1.6.0"]
|
||||||
[nubank/matcher-combinators "3.8.8"]
|
[nubank/matcher-combinators "3.9.1"]
|
||||||
|
|
||||||
;; Use the same version specified in the Nix dependency.
|
;; Use the same version specified in the Nix dependency.
|
||||||
[clj-kondo/clj-kondo "2024.03.13"]
|
[clj-kondo/clj-kondo "2024.03.13"]
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
legacy.status-im.multiaccounts.logout.core
|
legacy.status-im.multiaccounts.logout.core
|
||||||
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
||||||
legacy.status-im.multiaccounts.update.core
|
legacy.status-im.multiaccounts.update.core
|
||||||
legacy.status-im.network.net-info
|
|
||||||
legacy.status-im.pairing.core
|
legacy.status-im.pairing.core
|
||||||
legacy.status-im.profile.core
|
legacy.status-im.profile.core
|
||||||
legacy.status-im.search.core
|
legacy.status-im.search.core
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
(ns legacy.status-im.network.net-info
|
|
||||||
(:require
|
|
||||||
["@react-native-community/netinfo" :default net-info]
|
|
||||||
[native-module.core :as native-module]
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[taoensso.timbre :as log]
|
|
||||||
[utils.re-frame :as rf]))
|
|
||||||
|
|
||||||
(rf/defn change-network-status
|
|
||||||
[{:keys [db] :as cofx} is-connected?]
|
|
||||||
(rf/merge cofx
|
|
||||||
{:db (assoc db :network-status (if is-connected? :online :offline))}))
|
|
||||||
|
|
||||||
(rf/defn change-network-type
|
|
||||||
[{:keys [db] :as cofx} network-type expensive?]
|
|
||||||
(rf/merge cofx
|
|
||||||
{:db (assoc db :network/type network-type)
|
|
||||||
:network/notify-status-go [network-type expensive?]
|
|
||||||
:dispatch [:mobile-network/on-network-status-change]}))
|
|
||||||
|
|
||||||
(rf/defn handle-network-info-change
|
|
||||||
{:events [::network-info-changed]}
|
|
||||||
[{:keys [db] :as cofx} {:keys [isConnected type details] :as state}]
|
|
||||||
(let [old-network-status (:network-status db)
|
|
||||||
old-network-type (:network/type db)
|
|
||||||
connectivity-status (if isConnected :online :offline)
|
|
||||||
status-changed? (= connectivity-status old-network-status)
|
|
||||||
type-changed? (= type old-network-type)]
|
|
||||||
(log/debug "[net-info]"
|
|
||||||
"old-network-status" old-network-status
|
|
||||||
"old-network-type" old-network-type
|
|
||||||
"connectivity-status" connectivity-status
|
|
||||||
"type" type
|
|
||||||
"details" details)
|
|
||||||
(rf/merge cofx
|
|
||||||
(when-not status-changed?
|
|
||||||
(change-network-status isConnected))
|
|
||||||
(when-not type-changed?
|
|
||||||
(change-network-type type (:is-connection-expensive details))))))
|
|
||||||
|
|
||||||
(defn add-net-info-listener
|
|
||||||
[]
|
|
||||||
(when net-info
|
|
||||||
(.addEventListener ^js net-info
|
|
||||||
#(re-frame/dispatch [::network-info-changed
|
|
||||||
(js->clj % :keywordize-keys true)]))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:network/listen-to-network-info
|
|
||||||
(fn []
|
|
||||||
(add-net-info-listener)))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:network/notify-status-go
|
|
||||||
(fn [[network-type expensive?]]
|
|
||||||
(native-module/connection-change network-type expensive?)))
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[react-native.platform :as utils.platform]
|
[react-native.platform :as utils.platform]
|
||||||
[status-im.common.json-rpc.events :as json-rpc]
|
[status-im.common.json-rpc.events :as json-rpc]
|
||||||
|
[status-im.common.new-device-sheet.view :as new-device-sheet]
|
||||||
[status-im.config :as config]
|
[status-im.config :as config]
|
||||||
[status-im.navigation.events :as navigation]
|
[status-im.navigation.events :as navigation]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
@@ -220,6 +221,12 @@
|
|||||||
:name (:name metadata)
|
:name (:name metadata)
|
||||||
:device-type (:deviceType metadata))})
|
:device-type (:deviceType metadata))})
|
||||||
|
|
||||||
|
|
||||||
|
(defn should-show-syncing-pop-up?
|
||||||
|
[db installations]
|
||||||
|
(and (:syncing/pairing-process-initiated? db)
|
||||||
|
(first (filter #(not (get-in db [:pairing/installations (:id %)])) installations))))
|
||||||
|
|
||||||
(rf/defn handle-installations
|
(rf/defn handle-installations
|
||||||
[{:keys [db]} installations]
|
[{:keys [db]} installations]
|
||||||
{:db (update db
|
{:db (update db
|
||||||
@@ -228,7 +235,10 @@
|
|||||||
(fn [acc {:keys [id] :as i}]
|
(fn [acc {:keys [id] :as i}]
|
||||||
(update acc id merge (installation<-rpc i)))
|
(update acc id merge (installation<-rpc i)))
|
||||||
%
|
%
|
||||||
installations))})
|
installations))
|
||||||
|
:fx [(when-let [new-installation (should-show-syncing-pop-up? db installations)]
|
||||||
|
[:dispatch
|
||||||
|
[:show-bottom-sheet {:content (fn [] [new-device-sheet/view (:id new-installation)])}]])]})
|
||||||
|
|
||||||
(rf/defn load-installations
|
(rf/defn load-installations
|
||||||
{:events [:pairing.callback/get-our-installations-success]}
|
{:events [:pairing.callback/get-our-installations-success]}
|
||||||
@@ -243,6 +253,24 @@
|
|||||||
{}
|
{}
|
||||||
installations))})
|
installations))})
|
||||||
|
|
||||||
|
(rf/defn finish-seed-phrase-fallback-syncing
|
||||||
|
{:events [:pairing/finish-seed-phrase-fallback-syncing]}
|
||||||
|
[{:keys [db]}]
|
||||||
|
{:fx [[:dispatch [:show-bottom-sheet {:content (fn [] [new-device-sheet/view-2])}]]
|
||||||
|
[:json-rpc/call
|
||||||
|
[{:method "wakuext_finishPairingThroughSeedPhraseProcess"
|
||||||
|
:params [{:installationId (:syncing/installation-id db)}]
|
||||||
|
:js-response true
|
||||||
|
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]]]})
|
||||||
|
|
||||||
|
(rf/defn pair-and-sync
|
||||||
|
{:events [:pairing/pair-and-sync]}
|
||||||
|
[cofx installation-id]
|
||||||
|
{:fx [[:json-rpc/call
|
||||||
|
[{:method "wakuext_enableAndSyncInstallation"
|
||||||
|
:params [{:installationId installation-id}]
|
||||||
|
:on-success #(log/debug "successfully synced devices")}]]]})
|
||||||
|
|
||||||
(rf/defn enable-installation-success
|
(rf/defn enable-installation-success
|
||||||
{:events [:pairing.callback/enable-installation-success]}
|
{:events [:pairing.callback/enable-installation-success]}
|
||||||
[cofx installation-id]
|
[cofx installation-id]
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
||||||
(reg-root-key-sub :fleets/custom-fleets :custom-fleets)
|
(reg-root-key-sub :fleets/custom-fleets :custom-fleets)
|
||||||
(reg-root-key-sub :ui/search :ui/search)
|
(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 :peer-stats/count :peer-stats/count)
|
(reg-root-key-sub :peer-stats/count :peer-stats/count)
|
||||||
(reg-root-key-sub :peers-summary :peers-summary)
|
(reg-root-key-sub :peers-summary :peers-summary)
|
||||||
(reg-root-key-sub :web3-node-version :web3-node-version)
|
(reg-root-key-sub :web3-node-version :web3-node-version)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
[{:keys [current-log-level
|
[{:keys [current-log-level
|
||||||
telemetry-enabled?
|
telemetry-enabled?
|
||||||
light-client-enabled?
|
light-client-enabled?
|
||||||
|
store-confirmations-enabled?
|
||||||
current-fleet
|
current-fleet
|
||||||
test-networks-enabled?
|
test-networks-enabled?
|
||||||
is-goerli-enabled?
|
is-goerli-enabled?
|
||||||
@@ -77,6 +78,15 @@
|
|||||||
[:wakuv2.ui/toggle-light-client (not light-client-enabled?)])
|
[:wakuv2.ui/toggle-light-client (not light-client-enabled?)])
|
||||||
:accessory :switch
|
:accessory :switch
|
||||||
:active light-client-enabled?}
|
:active light-client-enabled?}
|
||||||
|
{:size :small
|
||||||
|
:title (i18n/label :t/store-confirmations)
|
||||||
|
:accessibility-label :store-confirmations
|
||||||
|
:container-margin-bottom 8
|
||||||
|
:on-press
|
||||||
|
#(re-frame/dispatch
|
||||||
|
[:wakuv2.ui/toggle-store-confirmations (not store-confirmations-enabled?)])
|
||||||
|
:accessory :switch
|
||||||
|
:active store-confirmations-enabled?}
|
||||||
{:size :small
|
{:size :small
|
||||||
:title "Testnet mode"
|
:title "Testnet mode"
|
||||||
:accessibility-label :test-networks-enabled
|
:accessibility-label :test-networks-enabled
|
||||||
@@ -114,13 +124,14 @@
|
|||||||
|
|
||||||
(views/defview advanced-settings
|
(views/defview advanced-settings
|
||||||
[]
|
[]
|
||||||
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
|
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
|
||||||
is-goerli-enabled? [:profile/is-goerli-enabled?]
|
is-goerli-enabled? [:profile/is-goerli-enabled?]
|
||||||
light-client-enabled? [:profile/light-client-enabled?]
|
light-client-enabled? [:profile/light-client-enabled?]
|
||||||
telemetry-enabled? [:profile/telemetry-enabled?]
|
store-confirmations-enabled? [:profile/store-confirmations-enabled?]
|
||||||
current-log-level [:log-level/current-log-level]
|
telemetry-enabled? [:profile/telemetry-enabled?]
|
||||||
current-fleet [:fleets/current-fleet]
|
current-log-level [:log-level/current-log-level]
|
||||||
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
|
current-fleet [:fleets/current-fleet]
|
||||||
|
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
|
||||||
[:<>
|
[:<>
|
||||||
[quo/page-nav
|
[quo/page-nav
|
||||||
{:type :title
|
{:type :title
|
||||||
@@ -130,13 +141,14 @@
|
|||||||
:on-press #(rf/dispatch [:navigate-back])}]
|
:on-press #(rf/dispatch [:navigate-back])}]
|
||||||
[list/flat-list
|
[list/flat-list
|
||||||
{:data (flat-list-data
|
{:data (flat-list-data
|
||||||
{:current-log-level current-log-level
|
{:current-log-level current-log-level
|
||||||
:telemetry-enabled? telemetry-enabled?
|
:telemetry-enabled? telemetry-enabled?
|
||||||
:light-client-enabled? light-client-enabled?
|
:light-client-enabled? light-client-enabled?
|
||||||
:current-fleet current-fleet
|
:store-confirmations-enabled? store-confirmations-enabled?
|
||||||
:dev-mode? false
|
:current-fleet current-fleet
|
||||||
:test-networks-enabled? test-networks-enabled?
|
:dev-mode? false
|
||||||
:is-goerli-enabled? is-goerli-enabled?
|
:test-networks-enabled? test-networks-enabled?
|
||||||
:peer-syncing-enabled? peer-syncing-enabled?})
|
:is-goerli-enabled? is-goerli-enabled?
|
||||||
|
:peer-syncing-enabled? peer-syncing-enabled?})
|
||||||
:key-fn (fn [_ i] (str i))
|
:key-fn (fn [_ i] (str i))
|
||||||
:render-fn render-item}]]))
|
:render-fn render-item}]]))
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
(ns legacy.status-im.utils.hex
|
|
||||||
(:require
|
|
||||||
[clojure.string :as string]))
|
|
||||||
|
|
||||||
(defn normalize-hex
|
|
||||||
[hex]
|
|
||||||
(when hex
|
|
||||||
(string/lower-case (if (string/starts-with? hex "0x")
|
|
||||||
(subs hex 2)
|
|
||||||
hex))))
|
|
||||||
|
|
||||||
(defn valid-hex?
|
|
||||||
[hex]
|
|
||||||
(let [hex (normalize-hex hex)]
|
|
||||||
(and (re-matches #"^[0-9a-fA-F]+$" hex)
|
|
||||||
(not= (js/parseInt hex 16) 0))))
|
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
[:app-state
|
[:app-state
|
||||||
:current-chat-id
|
:current-chat-id
|
||||||
:network
|
:network
|
||||||
:network-status
|
:network/status
|
||||||
:peers-summary
|
:peers-summary
|
||||||
:sync-state
|
:sync-state
|
||||||
:view-id
|
:view-id
|
||||||
|
|||||||
@@ -137,3 +137,19 @@
|
|||||||
:on-error #(log/error "failed to set light client"
|
:on-error #(log/error "failed to set light client"
|
||||||
{:error %
|
{:error %
|
||||||
:enabled? enabled?})}]})
|
:enabled? enabled?})}]})
|
||||||
|
|
||||||
|
(rf/defn toggle-store-confirmations
|
||||||
|
{:events [:wakuv2.ui/toggle-store-confirmations]}
|
||||||
|
[{:keys [db]} enabled?]
|
||||||
|
{:db (assoc-in db
|
||||||
|
[:profile/profile :wakuv2-config :EnableStoreConfirmationForMessagesSent]
|
||||||
|
enabled?)
|
||||||
|
|
||||||
|
:json-rpc/call [{:method "wakuext_setStoreConfirmationForMessagesSent"
|
||||||
|
:params [{:enabled enabled?}]
|
||||||
|
:on-success (fn []
|
||||||
|
(log/info "store confirmation set successfully" enabled?)
|
||||||
|
(re-frame/dispatch [:logout]))
|
||||||
|
:on-error #(log/error "failed to set store confirmation"
|
||||||
|
{:error %
|
||||||
|
:enabled? enabled?})}]})
|
||||||
|
|||||||
@@ -171,7 +171,7 @@
|
|||||||
#js
|
#js
|
||||||
{:getEnforcing {}})
|
{:getEnforcing {}})
|
||||||
|
|
||||||
(def net-info #js {})
|
(def net-info #js {:addEventListener identity})
|
||||||
(def react-native-biometrics #js {:default {}})
|
(def react-native-biometrics #js {:default {}})
|
||||||
(def react-native-static-safe-area-insets #js {:default {}})
|
(def react-native-static-safe-area-insets #js {:default {}})
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
(ns quo.components.avatars.token-avatar.view
|
(ns quo.components.avatars.token-avatar.view
|
||||||
(:require [quo.components.avatars.token-avatar.style :as style]
|
(:require [quo.components.avatars.token-avatar.style :as style]
|
||||||
|
[quo.components.utilities.token.view :as token]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.hole-view :as hole-view]
|
[react-native.hole-view :as hole-view]
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
@@ -12,13 +13,14 @@
|
|||||||
[:map {:closed true}
|
[:map {:closed true}
|
||||||
[:type {:optional true} [:enum :asset :collectible]]
|
[:type {:optional true} [:enum :asset :collectible]]
|
||||||
[:context? {:optional true} [:maybe :boolean]]
|
[:context? {:optional true} [:maybe :boolean]]
|
||||||
[:image :schema.common/image-source]
|
[:image {:optional true} [:maybe :schema.common/image-source]]
|
||||||
|
[:token {:optional true} [:maybe [:or :keyword :string]]]
|
||||||
[:network-image {:optional true} [:maybe :schema.common/image-source]]
|
[:network-image {:optional true} [:maybe :schema.common/image-source]]
|
||||||
[:container-style {:optional true} [:maybe :map]]]]]
|
[:container-style {:optional true} [:maybe :map]]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[{:keys [type context? image network-image container-style]}]
|
[{:keys [type context? image token network-image container-style]}]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (merge style/container container-style)
|
{:style (merge style/container container-style)
|
||||||
:accessibility-label :token-avatar}
|
:accessibility-label :token-avatar}
|
||||||
@@ -32,9 +34,11 @@
|
|||||||
[])
|
[])
|
||||||
:style style/hole-view}
|
:style style/hole-view}
|
||||||
platform/android? (assoc :key context?))
|
platform/android? (assoc :key context?))
|
||||||
[rn/image
|
[token/view
|
||||||
{:source image
|
{:size :size-32
|
||||||
:style (style/image type)}]]
|
:token token
|
||||||
|
:style (style/image type)
|
||||||
|
:image-source image}]]
|
||||||
(when context?
|
(when context?
|
||||||
[rn/image
|
[rn/image
|
||||||
{:source network-image
|
{:source network-image
|
||||||
|
|||||||
@@ -21,15 +21,17 @@
|
|||||||
(colors/theme-colors colors/white colors/neutral-95 theme))})
|
(colors/theme-colors colors/white colors/neutral-95 theme))})
|
||||||
|
|
||||||
(defn buttons-container
|
(defn buttons-container
|
||||||
[actions]
|
[actions container-style]
|
||||||
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
|
(merge
|
||||||
:justify-content :space-around
|
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
|
||||||
:padding-vertical 12
|
:justify-content :space-around
|
||||||
:gap 12
|
:padding-vertical 12
|
||||||
:padding-horizontal 20})
|
:gap 12
|
||||||
|
:padding-horizontal 20}
|
||||||
|
container-style))
|
||||||
|
|
||||||
(def button-container
|
(def button-container
|
||||||
{:flex 1})
|
{:flex-grow 1})
|
||||||
|
|
||||||
(def description-top
|
(def description-top
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
[:button-two-props {:optional true} [:maybe :map]]
|
[:button-two-props {:optional true} [:maybe :map]]
|
||||||
[:scroll? {:optional true} [:maybe :boolean]]
|
[:scroll? {:optional true} [:maybe :boolean]]
|
||||||
[:blur? {:optional true} [:maybe :boolean]]
|
[:blur? {:optional true} [:maybe :boolean]]
|
||||||
[:container-style {:optional true} [:maybe :map]]]]]
|
[:container-style {:optional true} [:maybe :map]]
|
||||||
|
[:buttons-container-style {:optional true} [:maybe :map]]]]]
|
||||||
:any])
|
:any])
|
||||||
|
|
||||||
(def ^:private role-icon
|
(def ^:private role-icon
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[{:keys [actions description description-text description-top-text error-message role button-one-label
|
[{:keys [actions description description-text description-top-text error-message role button-one-label
|
||||||
button-two-label blur? button-one-props button-two-props scroll? container-style
|
button-two-label blur? button-one-props button-two-props scroll? container-style
|
||||||
context-tag-props]}]
|
buttons-container-style context-tag-props]}]
|
||||||
(let [theme (quo.theme/use-theme)]
|
(let [theme (quo.theme/use-theme)]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (merge (style/container scroll? blur? theme) container-style)}
|
{:style (merge (style/container scroll? blur? theme) container-style)}
|
||||||
@@ -72,14 +73,14 @@
|
|||||||
:context (i18n/label (keyword "t" role))}
|
:context (i18n/label (keyword "t" role))}
|
||||||
context-tag-props)]])
|
context-tag-props)]])
|
||||||
|
|
||||||
[rn/view {:style (style/buttons-container actions)}
|
[rn/view {:style (style/buttons-container actions buttons-container-style)}
|
||||||
(when (or (= actions :two-actions)
|
(when (or (= actions :two-actions)
|
||||||
(= actions :two-vertical-actions))
|
(= actions :two-vertical-actions))
|
||||||
[button/button
|
[button/button
|
||||||
(merge
|
(merge
|
||||||
{:size 40
|
{:size 40
|
||||||
:background (when (or blur? scroll?) :blur)
|
|
||||||
:container-style style/button-container
|
:container-style style/button-container
|
||||||
|
:background (when (or blur? scroll?) :blur)
|
||||||
:theme theme
|
:theme theme
|
||||||
:accessibility-label :button-two}
|
:accessibility-label :button-two}
|
||||||
button-two-props)
|
button-two-props)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
{:type :spending-cap
|
{:type :spending-cap
|
||||||
:label "Spending Cap"
|
:label "Spending Cap"
|
||||||
:button-label "Edit"
|
:button-label "Edit"
|
||||||
|
:button-icon :i/options
|
||||||
:on-button-press on-button-press
|
:on-button-press on-button-press
|
||||||
:avatar-props {:image "image"}}])
|
:avatar-props {:image "image"}}])
|
||||||
(h/fire-event :press (h/get-by-text "Edit"))
|
(h/fire-event :press (h/get-by-text "Edit"))
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
:style (style/description blur? theme)}
|
:style (style/description blur? theme)}
|
||||||
description])]
|
description])]
|
||||||
(when (= type :account) [tiny-tag/view {:label tag-label}])
|
(when (= type :account) [tiny-tag/view {:label tag-label}])
|
||||||
(when (= type :spending-cap)
|
(when (and (= type :spending-cap) button-icon)
|
||||||
[button/button
|
[button/button
|
||||||
{:type :outline
|
{:type :outline
|
||||||
:size 24
|
:size 24
|
||||||
|
|||||||
@@ -47,3 +47,12 @@
|
|||||||
(defn style-text-value
|
(defn style-text-value
|
||||||
[theme]
|
[theme]
|
||||||
{:color (colors/theme-colors colors/neutral-50 colors/white theme)})
|
{:color (colors/theme-colors colors/neutral-50 colors/white theme)})
|
||||||
|
|
||||||
|
(def initials-avatar-container
|
||||||
|
{:width 32
|
||||||
|
:height 32})
|
||||||
|
|
||||||
|
(def image-avatar
|
||||||
|
{:width 32
|
||||||
|
:height 32
|
||||||
|
:border-radius 32})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
(ns quo.components.list-items.dapp.view
|
(ns quo.components.list-items.dapp.view
|
||||||
(:require
|
(:require
|
||||||
|
[quo.components.avatars.user-avatar.view :as user-avatar]
|
||||||
[quo.components.list-items.dapp.style :as style]
|
[quo.components.list-items.dapp.style :as style]
|
||||||
[quo.components.markdown.text :as text]
|
[quo.components.markdown.text :as text]
|
||||||
[quo.theme :as quo.theme]
|
[quo.theme :as quo.theme]
|
||||||
@@ -20,9 +21,15 @@
|
|||||||
:on-press-in on-press-in
|
:on-press-in on-press-in
|
||||||
:on-press-out on-press-out}
|
:on-press-out on-press-out}
|
||||||
[rn/view {:style style/container-info}
|
[rn/view {:style style/container-info}
|
||||||
[fast-image/fast-image
|
(if (:avatar dapp)
|
||||||
{:source (:avatar dapp)
|
[fast-image/fast-image
|
||||||
:style {:width 32 :height 32}}]
|
{:source (:avatar dapp)
|
||||||
|
:style style/image-avatar}]
|
||||||
|
[rn/view {:style style/initials-avatar-container}
|
||||||
|
[user-avatar/initials-avatar
|
||||||
|
{:full-name (:name dapp)
|
||||||
|
:size :small
|
||||||
|
:customization-color (:customization-color dapp)}]])
|
||||||
[rn/view {:style style/user-info}
|
[rn/view {:style style/user-info}
|
||||||
[text/text
|
[text/text
|
||||||
{:weight :semi-bold
|
{:weight :semi-bold
|
||||||
|
|||||||
@@ -79,14 +79,20 @@
|
|||||||
[counter-view counter])
|
[counter-view counter])
|
||||||
[rn/view {:style (style/collectible-border theme)}]]]))
|
[rn/view {:style (style/collectible-border theme)}]]]))
|
||||||
|
|
||||||
|
(defn invalid-image?
|
||||||
|
[image-src]
|
||||||
|
(or (nil? image-src)
|
||||||
|
(string/blank? image-src)))
|
||||||
|
|
||||||
(defn view-internal
|
(defn view-internal
|
||||||
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
|
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
|
||||||
on-collectible-load aspect-ratio gradient-color-index]
|
on-collectible-load aspect-ratio gradient-color-index]
|
||||||
:or {gradient-color-index :gradient-1
|
:or {gradient-color-index :gradient-1
|
||||||
on-collectible-load (fn [])}}]
|
on-collectible-load (fn [])}}]
|
||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
[error? set-error] (rn/use-state (or (nil? image-src)
|
[error? set-error] (rn/use-state (invalid-image? image-src))]
|
||||||
(string/blank? image-src)))]
|
(rn/use-effect #(set-error (invalid-image? image-src))
|
||||||
|
[image-src])
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:style (merge container-style (style/container aspect-ratio))
|
{:style (merge container-style (style/container aspect-ratio))
|
||||||
:accessibility-label :expanded-collectible
|
:accessibility-label :expanded-collectible
|
||||||
|
|||||||
@@ -121,6 +121,7 @@
|
|||||||
[:card? {:optional true} [:maybe :boolean]]
|
[:card? {:optional true} [:maybe :boolean]]
|
||||||
[:right-icon {:optional true} [:maybe :keyword]]
|
[:right-icon {:optional true} [:maybe :keyword]]
|
||||||
[:right-content {:optional true} [:maybe :map]]
|
[:right-content {:optional true} [:maybe :map]]
|
||||||
|
[:icon-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||||
[:status {:optional true} [:maybe [:enum :default :loading]]]
|
[:status {:optional true} [:maybe [:enum :default :loading]]]
|
||||||
[:subtitle-type {:optional true} [:maybe [:enum :default :icon :network :account :editable]]]
|
[:subtitle-type {:optional true} [:maybe [:enum :default :icon :network :account :editable]]]
|
||||||
[:size {:optional true} [:maybe [:enum :default :small :large]]]
|
[:size {:optional true} [:maybe [:enum :default :small :large]]]
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
(ns quo.components.slideshow.slider-bar.component-spec
|
||||||
|
(:require
|
||||||
|
[quo.components.slideshow.slider-bar.view :as slider-bar]
|
||||||
|
[test-helpers.component :as h]))
|
||||||
|
|
||||||
|
(h/describe "Slideshow: slider-bar"
|
||||||
|
(h/test "default render"
|
||||||
|
(h/render-with-theme-provider [slider-bar/view {:accessibility-label :slider-bar}])
|
||||||
|
(h/is-truthy (h/query-by-label-text :slider-bar)))
|
||||||
|
|
||||||
|
(h/test "render with total-amount and active-index"
|
||||||
|
(h/render-with-theme-provider [slider-bar/view
|
||||||
|
{:total-amount 4
|
||||||
|
:active-index 1
|
||||||
|
:accessibility-label :slider-bar}])
|
||||||
|
(h/is-truthy (h/query-by-label-text :slider-bar))
|
||||||
|
(h/is-equal 4 (count (h/query-all-by-label-text :slide-bar-item))))
|
||||||
|
|
||||||
|
(h/test "render with total-amount active-index and possible scroll"
|
||||||
|
(h/render-with-theme-provider [slider-bar/view
|
||||||
|
{:total-amount 10
|
||||||
|
:active-index 7
|
||||||
|
:accessibility-label :slider-bar}])
|
||||||
|
(h/is-truthy (h/query-by-label-text :slider-bar))
|
||||||
|
(h/is-equal 10 (count (h/query-all-by-label-text :slide-bar-item)))))
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
(ns quo.components.slideshow.slider-bar.schema)
|
||||||
|
|
||||||
|
(def ?schema
|
||||||
|
[:=>
|
||||||
|
[:cat
|
||||||
|
[:map {:closed true}
|
||||||
|
[:total-amount {:optional true} [:maybe :int]]
|
||||||
|
[:active-index {:optional true} :int]
|
||||||
|
[:customization-color {:optional true}
|
||||||
|
[:maybe :schema.common/customization-color]]
|
||||||
|
[:blur? {:optional true} [:maybe :boolean]]
|
||||||
|
[:accessibility-label {:optional true} [:maybe :keyword]]
|
||||||
|
[:container-style {:optional true} [:maybe :map]]]]
|
||||||
|
:any])
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
(ns quo.components.slideshow.slider-bar.style
|
||||||
|
(:require
|
||||||
|
[quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def list-wrapper
|
||||||
|
{:align-items :center})
|
||||||
|
|
||||||
|
(defn list-bar
|
||||||
|
[bar-width]
|
||||||
|
{:width bar-width})
|
||||||
|
|
||||||
|
(defn item-wrapper
|
||||||
|
[{:keys [size spacing]}]
|
||||||
|
{:width size
|
||||||
|
:height size
|
||||||
|
:margin-left spacing
|
||||||
|
:flex 1
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(defn item
|
||||||
|
[{:keys [size spacing active? customization-color theme blur?]}]
|
||||||
|
{:width size
|
||||||
|
:height size
|
||||||
|
:border-radius spacing
|
||||||
|
:background-color
|
||||||
|
(cond
|
||||||
|
(and blur? active?) colors/white
|
||||||
|
(and blur? (not active?)) colors/white-opa-10
|
||||||
|
(and (not blur?) active?) (colors/resolve-color customization-color theme)
|
||||||
|
:else (colors/theme-colors colors/neutral-20 colors/neutral-80 theme))})
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
(ns quo.components.slideshow.slider-bar.view
|
||||||
|
(:require
|
||||||
|
[quo.components.slideshow.slider-bar.schema :as component-schema]
|
||||||
|
[quo.components.slideshow.slider-bar.style :as style]
|
||||||
|
[quo.theme]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[schema.core :as schema]))
|
||||||
|
|
||||||
|
(def item-size 8)
|
||||||
|
(def item-spacing item-size)
|
||||||
|
(def max-length 6)
|
||||||
|
(def bar-width (* (+ item-spacing item-size) max-length))
|
||||||
|
|
||||||
|
(def micro-scale 0.25)
|
||||||
|
(def small-scale 0.5)
|
||||||
|
(def medium-scale 0.75)
|
||||||
|
(def default-scale 1)
|
||||||
|
|
||||||
|
(def items-before-scroll
|
||||||
|
(/ max-length 2))
|
||||||
|
|
||||||
|
(defn- calc-relative-index
|
||||||
|
"Calculates item index in visible area"
|
||||||
|
[index active-index total-length]
|
||||||
|
(let [last-index (dec total-length)]
|
||||||
|
(cond
|
||||||
|
(< active-index items-before-scroll) index
|
||||||
|
(> active-index
|
||||||
|
(- last-index items-before-scroll)) (+ (- index total-length) max-length)
|
||||||
|
:else (+ (- index active-index) items-before-scroll))))
|
||||||
|
|
||||||
|
(defn- calc-first-item-scale
|
||||||
|
"Calculates scale for first item in visible area"
|
||||||
|
[active-index]
|
||||||
|
(cond
|
||||||
|
(= active-index items-before-scroll) medium-scale
|
||||||
|
(> active-index items-before-scroll) small-scale
|
||||||
|
:else default-scale))
|
||||||
|
|
||||||
|
(defn- calc-second-item-scale
|
||||||
|
"Calculates scale for second item in visible area"
|
||||||
|
[active-index]
|
||||||
|
(if (> active-index items-before-scroll)
|
||||||
|
medium-scale
|
||||||
|
default-scale))
|
||||||
|
|
||||||
|
(defn- calc-last-item-scale
|
||||||
|
"Calculates scale for last item in visible area"
|
||||||
|
[active-index total-length]
|
||||||
|
(let [last-index (dec total-length)]
|
||||||
|
(if (> active-index (- last-index items-before-scroll))
|
||||||
|
medium-scale
|
||||||
|
small-scale)))
|
||||||
|
|
||||||
|
(defn- calc-last-but-one-item-scale
|
||||||
|
"Calculates scale for before last item in visible area"
|
||||||
|
[active-index total-length]
|
||||||
|
(if (> active-index (- (dec total-length) items-before-scroll))
|
||||||
|
default-scale
|
||||||
|
medium-scale))
|
||||||
|
|
||||||
|
(defn- get-scale
|
||||||
|
[index active-index total-length]
|
||||||
|
(let [relative-index (calc-relative-index index active-index total-length)]
|
||||||
|
(if (or (= index active-index)
|
||||||
|
(< total-length max-length))
|
||||||
|
default-scale
|
||||||
|
(cond
|
||||||
|
(< relative-index 0) micro-scale
|
||||||
|
(= relative-index 0) (calc-first-item-scale active-index)
|
||||||
|
(= relative-index 1) (calc-second-item-scale active-index)
|
||||||
|
(= relative-index 4) (calc-last-but-one-item-scale active-index total-length)
|
||||||
|
(= relative-index 5) (calc-last-item-scale active-index total-length)
|
||||||
|
(> relative-index 5) micro-scale
|
||||||
|
:else
|
||||||
|
default-scale))))
|
||||||
|
|
||||||
|
(defn- bar-item
|
||||||
|
[index _ _ {:keys [active-index total-length customization-color theme blur?]}]
|
||||||
|
(let [active? (= index active-index)
|
||||||
|
shared-scale (reanimated/use-shared-value (get-scale index active-index total-length))]
|
||||||
|
(rn/use-effect (fn []
|
||||||
|
(let [new-scale-value (get-scale index active-index total-length)]
|
||||||
|
(reanimated/animate shared-scale new-scale-value)))
|
||||||
|
[index active-index total-length])
|
||||||
|
[rn/view
|
||||||
|
{:key index
|
||||||
|
:style (style/item-wrapper {:size item-size
|
||||||
|
:spacing item-spacing})}
|
||||||
|
[reanimated/view
|
||||||
|
{:accessibility-label :slide-bar-item
|
||||||
|
:style
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:transform [{:scale shared-scale}]}
|
||||||
|
(style/item {:size item-size
|
||||||
|
:spacing item-spacing
|
||||||
|
:active? active?
|
||||||
|
:customization-color customization-color
|
||||||
|
:theme theme
|
||||||
|
:blur? blur?}))}]]))
|
||||||
|
|
||||||
|
(defn- get-item-layout
|
||||||
|
[_ index]
|
||||||
|
(let [length (+ item-size item-spacing)]
|
||||||
|
#js {:length length
|
||||||
|
:index index
|
||||||
|
:offset (* index length)}))
|
||||||
|
|
||||||
|
(defn- view-internal
|
||||||
|
[{:keys [customization-color blur? accessibility-label container-style]
|
||||||
|
:as props}]
|
||||||
|
(let [active-index (or (:active-index props) 0)
|
||||||
|
total-amount (or (:total-amount props) 1)
|
||||||
|
theme (quo.theme/use-theme)
|
||||||
|
flat-list-ref (rn/use-ref-atom nil)
|
||||||
|
set-flat-list-ref (rn/use-callback #(reset! flat-list-ref %))
|
||||||
|
center-position 0.5
|
||||||
|
data (range total-amount)
|
||||||
|
scroll-to-index (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(some-> ^js @flat-list-ref
|
||||||
|
(.scrollToIndex #js {:animated true
|
||||||
|
:index active-index
|
||||||
|
:viewOffset item-spacing
|
||||||
|
:viewPosition center-position})))
|
||||||
|
[flat-list-ref active-index])]
|
||||||
|
(rn/use-effect scroll-to-index [active-index])
|
||||||
|
[rn/view
|
||||||
|
{:style (merge style/list-wrapper container-style)
|
||||||
|
:accessibility-label accessibility-label}
|
||||||
|
[reanimated/flat-list
|
||||||
|
{:style (style/list-bar bar-width)
|
||||||
|
:data data
|
||||||
|
:scroll-enabled false
|
||||||
|
:ref set-flat-list-ref
|
||||||
|
:shows-horizontal-scroll-indicator false
|
||||||
|
:bounces false
|
||||||
|
:horizontal true
|
||||||
|
:extra-data (str active-index)
|
||||||
|
:render-data {:active-index active-index
|
||||||
|
:total-length total-amount
|
||||||
|
:customization-color customization-color
|
||||||
|
:theme theme
|
||||||
|
:blur? blur?}
|
||||||
|
:get-item-layout get-item-layout
|
||||||
|
:render-fn bar-item
|
||||||
|
:key-fn identity}]]))
|
||||||
|
|
||||||
|
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
(def ^:private ?network
|
(def ^:private ?network
|
||||||
[:map
|
[:map
|
||||||
[:network-logo {:optional true} [:maybe :schema.common/image-source]]
|
[:network-logo {:optional true} [:maybe :schema.common/image-source]]
|
||||||
[:network-name {:optional true} [:maybe :string]]])
|
[:network-name {:optional true} [:maybe [:or :string :keyword]]]])
|
||||||
|
|
||||||
(def ^:private ?multinetwork
|
(def ^:private ?multinetwork
|
||||||
[:map
|
[:map
|
||||||
|
|||||||
@@ -41,7 +41,8 @@
|
|||||||
:align-items :center
|
:align-items :center
|
||||||
:height size
|
:height size
|
||||||
:background-color background-color
|
:background-color background-color
|
||||||
:border-radius border-radius}
|
:border-radius border-radius
|
||||||
|
:flex-shrink 1}
|
||||||
(= state :selected) (assoc :height (+ size 2)
|
(= state :selected) (assoc :height (+ size 2)
|
||||||
:border-color border-color
|
:border-color border-color
|
||||||
:border-width 1))))
|
:border-width 1))))
|
||||||
@@ -50,11 +51,13 @@
|
|||||||
[size]
|
[size]
|
||||||
{:margin-right (if (= size 24) 6 10)
|
{:margin-right (if (= size 24) 6 10)
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
|
:flex-shrink 1
|
||||||
:align-items :center})
|
:align-items :center})
|
||||||
|
|
||||||
(defn tag-spacing
|
(defn tag-spacing
|
||||||
[size]
|
[size shrinkable?]
|
||||||
{:margin-left (if (= size 24) 4 8)})
|
(cond-> {:margin-left (if (= size 24) 4 8)}
|
||||||
|
shrinkable? (assoc :flex-shrink 1)))
|
||||||
|
|
||||||
(defn text
|
(defn text
|
||||||
[theme]
|
[theme]
|
||||||
|
|||||||
@@ -17,17 +17,19 @@
|
|||||||
[schema.core :as schema]))
|
[schema.core :as schema]))
|
||||||
|
|
||||||
(defn- tag-skeleton
|
(defn- tag-skeleton
|
||||||
[{:keys [size text theme]
|
[{:keys [size text theme shrinkable?]
|
||||||
:or {size 24
|
:or {size 24
|
||||||
theme (quo.theme/use-theme)}}
|
theme (quo.theme/use-theme)}}
|
||||||
logo-component]
|
logo-component]
|
||||||
[rn/view {:style (style/tag-container size)}
|
[rn/view {:style (style/tag-container size)}
|
||||||
logo-component
|
logo-component
|
||||||
[rn/view {:style (style/tag-spacing size)}
|
[rn/view {:style (style/tag-spacing size shrinkable?)}
|
||||||
[text/text
|
[text/text
|
||||||
{:style (style/text theme)
|
{:style (style/text theme)
|
||||||
:weight :medium
|
:weight :medium
|
||||||
:size (if (= size 24) :paragraph-2 :paragraph-1)}
|
:size (if (= size 24) :paragraph-2 :paragraph-1)
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsize-mode :middle}
|
||||||
text]]])
|
text]]])
|
||||||
|
|
||||||
(defn- communities-tag
|
(defn- communities-tag
|
||||||
@@ -37,7 +39,7 @@
|
|||||||
icon-size (if (= size 24) 16 20)]
|
icon-size (if (= size 24) 16 20)]
|
||||||
[rn/view {:style (style/tag-container size)}
|
[rn/view {:style (style/tag-container size)}
|
||||||
[fast-image/fast-image {:style (style/circle-logo size) :source community-logo}]
|
[fast-image/fast-image {:style (style/circle-logo size) :source community-logo}]
|
||||||
[rn/view {:style (style/tag-spacing size)}
|
[rn/view {:style (style/tag-spacing size false)}
|
||||||
[text/text
|
[text/text
|
||||||
{:style (style/text theme)
|
{:style (style/text theme)
|
||||||
:weight :medium
|
:weight :medium
|
||||||
@@ -148,9 +150,10 @@
|
|||||||
|
|
||||||
:collectible
|
:collectible
|
||||||
[tag-skeleton
|
[tag-skeleton
|
||||||
{:theme theme
|
{:theme theme
|
||||||
:size size
|
:size size
|
||||||
:text (str collectible-name " #" collectible-number)}
|
:text (str collectible-name " #" collectible-number)
|
||||||
|
:shrinkable? true}
|
||||||
[rn/image {:style (style/rounded-logo size) :source collectible}]]
|
[rn/image {:style (style/rounded-logo size) :source collectible}]]
|
||||||
|
|
||||||
:account
|
:account
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
(ns quo.components.wallet.swap-input.component-spec
|
||||||
|
(:require [quo.components.wallet.swap-input.view :as swap-input]
|
||||||
|
[test-helpers.component :as h]))
|
||||||
|
|
||||||
|
(h/describe "Wallet: Swap Input"
|
||||||
|
(h/test "should render correctly with props"
|
||||||
|
(h/render-with-theme-provider
|
||||||
|
[swap-input/view
|
||||||
|
{:type :pay
|
||||||
|
:error? false
|
||||||
|
:token "SNT"
|
||||||
|
:status :default
|
||||||
|
:currency-symbol "€"
|
||||||
|
:value "5"
|
||||||
|
:fiat-value "1.50"
|
||||||
|
:network-tag-props {:title "Max: 200 SNT"}}])
|
||||||
|
(h/is-truthy (h/get-by-label-text :swap-input))
|
||||||
|
(h/is-truthy (h/get-by-text "SNT"))
|
||||||
|
(h/is-truthy (h/get-by-text "€1.50"))
|
||||||
|
(h/is-truthy (h/get-by-text "Max: 200 SNT")))
|
||||||
|
|
||||||
|
(h/test "should render correctly with approval label"
|
||||||
|
(h/render-with-theme-provider
|
||||||
|
[swap-input/view
|
||||||
|
{:type :pay
|
||||||
|
:show-approval-label? true
|
||||||
|
:approval-label-props
|
||||||
|
{:status :approve
|
||||||
|
:token-value "10"
|
||||||
|
:token-symbol "SNT"}}])
|
||||||
|
(h/is-truthy (h/get-by-text "Approve 10 SNT"))))
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
(ns quo.components.wallet.swap-input.style
|
||||||
|
(:require [quo.foundations.colors :as colors]
|
||||||
|
[quo.foundations.typography :as typography]))
|
||||||
|
|
||||||
|
(defn- border-color
|
||||||
|
[theme]
|
||||||
|
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))
|
||||||
|
|
||||||
|
(defn- loader-color
|
||||||
|
[theme]
|
||||||
|
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))
|
||||||
|
|
||||||
|
(defn content
|
||||||
|
[theme]
|
||||||
|
{:border-width 1
|
||||||
|
:border-radius 16
|
||||||
|
:border-color (border-color theme)
|
||||||
|
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
|
||||||
|
|
||||||
|
(defn row-1
|
||||||
|
[loading?]
|
||||||
|
{:padding 12
|
||||||
|
:gap 8
|
||||||
|
:align-items (if loading? :center :flex-end)
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
|
(defn row-1-loader
|
||||||
|
[theme]
|
||||||
|
{:width 74
|
||||||
|
:height 14
|
||||||
|
:border-radius 6
|
||||||
|
:background-color (loader-color theme)})
|
||||||
|
|
||||||
|
(def input-container
|
||||||
|
{:flex 1
|
||||||
|
:flex-direction :row
|
||||||
|
:gap 5
|
||||||
|
:height 32
|
||||||
|
:align-items :flex-end})
|
||||||
|
|
||||||
|
(defn input
|
||||||
|
[disabled? error? theme]
|
||||||
|
(assoc typography/font-semi-bold
|
||||||
|
:font-size 27
|
||||||
|
:flex-shrink 1
|
||||||
|
:padding 0
|
||||||
|
:color (cond
|
||||||
|
error? (colors/resolve-color :danger theme)
|
||||||
|
disabled? (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||||
|
:else (colors/theme-colors colors/neutral-100 colors/white theme))
|
||||||
|
:line-height 32))
|
||||||
|
|
||||||
|
(defn token-symbol
|
||||||
|
[theme]
|
||||||
|
{:padding-bottom 3
|
||||||
|
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||||
|
|
||||||
|
(defn row-2
|
||||||
|
[align-right?]
|
||||||
|
{:flex-direction :row
|
||||||
|
:justify-content (if align-right? :flex-end :space-between)
|
||||||
|
:align-items :center
|
||||||
|
:padding 12})
|
||||||
|
|
||||||
|
(defn row-2-loader
|
||||||
|
[theme]
|
||||||
|
{:width 80
|
||||||
|
:height 10
|
||||||
|
:margin-vertical 7
|
||||||
|
:border-radius 6
|
||||||
|
:background-color (loader-color theme)})
|
||||||
|
|
||||||
|
(def fiat-amount
|
||||||
|
{:color colors/neutral-50})
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
(ns quo.components.wallet.swap-input.view
|
||||||
|
(:require [oops.core :as oops]
|
||||||
|
[quo.components.avatars.token-avatar.view :as token-avatar]
|
||||||
|
[quo.components.buttons.button.view :as buttons]
|
||||||
|
[quo.components.dividers.divider-line.view :as divider-line]
|
||||||
|
[quo.components.markdown.text :as text]
|
||||||
|
[quo.components.tags.network-tags.view :as network-tag]
|
||||||
|
[quo.components.wallet.approval-label.schema :as approval-label.schema]
|
||||||
|
[quo.components.wallet.approval-label.view :as approval-label]
|
||||||
|
[quo.components.wallet.swap-input.style :as style]
|
||||||
|
[quo.foundations.colors :as colors]
|
||||||
|
quo.theme
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[schema.core :as schema]))
|
||||||
|
|
||||||
|
(def ?schema
|
||||||
|
[:=>
|
||||||
|
[:catn
|
||||||
|
[:props
|
||||||
|
[:map {:closed true}
|
||||||
|
[:type {:optional true} [:maybe [:enum :pay :receive]]]
|
||||||
|
[:status {:optional true} [:maybe [:enum :default :disabled :loading]]]
|
||||||
|
[:token {:optional true} [:maybe :string]]
|
||||||
|
[:value {:optional true} [:maybe :string]]
|
||||||
|
[:default-value {:optional true} [:maybe :string]]
|
||||||
|
[:currency-symbol {:optional true} [:maybe :string]]
|
||||||
|
[:fiat-value {:optional true} [:maybe :string]]
|
||||||
|
[:show-approval-label? {:optional true} [:maybe :boolean]]
|
||||||
|
[:error? {:optional true} [:maybe :boolean]]
|
||||||
|
[:show-keyboard? {:optional true} [:maybe :boolean]]
|
||||||
|
[:approval-label-props {:optional true} [:maybe approval-label.schema/?schema]]
|
||||||
|
[:network-tag-props {:optional true} [:maybe :map]]
|
||||||
|
[:on-change-text {:optional true} [:maybe fn?]]
|
||||||
|
[:enable-swap? {:optional true} [:maybe :boolean]]
|
||||||
|
[:on-swap-press {:optional true} [:maybe fn?]]
|
||||||
|
[:on-token-press {:optional true} [:maybe fn?]]
|
||||||
|
[:on-max-press {:optional true} [:maybe fn?]]
|
||||||
|
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||||
|
[:container-style {:optional true} [:maybe :map]]]]]
|
||||||
|
:any])
|
||||||
|
|
||||||
|
(defn view-internal
|
||||||
|
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
|
||||||
|
approval-label-props default-value enable-swap?
|
||||||
|
currency-symbol on-change-text show-keyboard?
|
||||||
|
container-style on-swap-press on-token-press on-max-press]}]
|
||||||
|
(let [theme (quo.theme/use-theme)
|
||||||
|
pay? (= type :pay)
|
||||||
|
disabled? (= status :disabled)
|
||||||
|
loading? (= status :loading)
|
||||||
|
controlled-input? (some? value)
|
||||||
|
input-ref (rn/use-ref-atom nil)
|
||||||
|
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)) [])
|
||||||
|
focus-input (rn/use-callback (fn []
|
||||||
|
(some-> @input-ref
|
||||||
|
(oops/ocall "focus")))
|
||||||
|
[input-ref])]
|
||||||
|
[rn/view
|
||||||
|
{:style container-style
|
||||||
|
:accessibility-label :swap-input}
|
||||||
|
[rn/view {:style (style/content theme)}
|
||||||
|
[rn/view
|
||||||
|
{:style (style/row-1 loading?)}
|
||||||
|
[rn/pressable {:on-press on-token-press}
|
||||||
|
[token-avatar/view
|
||||||
|
{:type :asset
|
||||||
|
:token token}]]
|
||||||
|
(if loading?
|
||||||
|
[rn/view {:style (style/row-1-loader theme)}]
|
||||||
|
[:<>
|
||||||
|
[rn/pressable
|
||||||
|
{:style style/input-container
|
||||||
|
:on-press focus-input}
|
||||||
|
[rn/text-input
|
||||||
|
(cond-> {:ref set-input-ref
|
||||||
|
:style (style/input disabled? error? theme)
|
||||||
|
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||||
|
colors/neutral-50
|
||||||
|
theme)
|
||||||
|
:keyboard-type :numeric
|
||||||
|
:auto-focus true
|
||||||
|
:on-change-text on-change-text
|
||||||
|
:show-soft-input-on-focus show-keyboard?
|
||||||
|
:default-value default-value
|
||||||
|
:placeholder "0"}
|
||||||
|
controlled-input? (assoc :value value))]
|
||||||
|
[text/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :semi-bold
|
||||||
|
:style (style/token-symbol theme)}
|
||||||
|
token]]
|
||||||
|
(when (and pay? enable-swap?)
|
||||||
|
[buttons/button
|
||||||
|
{:type :outline
|
||||||
|
:size 32
|
||||||
|
:on-press on-swap-press
|
||||||
|
:icon-only? true}
|
||||||
|
:i/reorder])])]
|
||||||
|
[divider-line/view]
|
||||||
|
[rn/view
|
||||||
|
{:style (style/row-2 (or (not pay?) loading?))}
|
||||||
|
(when-not loading?
|
||||||
|
[:<>
|
||||||
|
(when pay?
|
||||||
|
[rn/pressable {:on-press on-max-press}
|
||||||
|
[network-tag/view
|
||||||
|
(assoc network-tag-props
|
||||||
|
:status
|
||||||
|
(if error? :error :default))]])
|
||||||
|
[text/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style style/fiat-amount
|
||||||
|
:weight :medium}
|
||||||
|
(str currency-symbol fiat-value)]])
|
||||||
|
(when loading?
|
||||||
|
[rn/view {:style (style/row-2-loader theme)}])]]
|
||||||
|
(when (and (not= status :loading) (= type :pay) show-approval-label?)
|
||||||
|
[approval-label/view
|
||||||
|
approval-label-props])]))
|
||||||
|
|
||||||
|
(def view (schema/instrument #'view-internal ?schema))
|
||||||
@@ -51,8 +51,7 @@
|
|||||||
|
|
||||||
(defn prop-text
|
(defn prop-text
|
||||||
[theme]
|
[theme]
|
||||||
{:margin-right 4
|
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
|
||||||
|
|
||||||
(def icon-container
|
(def icon-container
|
||||||
{:width 32
|
{:width 32
|
||||||
@@ -61,12 +60,15 @@
|
|||||||
|
|
||||||
(def container
|
(def container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
|
:flex 1
|
||||||
:column-gap 8})
|
:column-gap 8})
|
||||||
|
|
||||||
(def content-line
|
(def content-line
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:margin-top 2
|
:margin-top 2
|
||||||
:align-items :center})
|
:align-items :center
|
||||||
|
:column-gap 4
|
||||||
|
:justify-content :flex-start})
|
||||||
|
|
||||||
(def icon-hole-view
|
(def icon-hole-view
|
||||||
{:width 32
|
{:width 32
|
||||||
|
|||||||
@@ -98,8 +98,11 @@
|
|||||||
|
|
||||||
(defn prop-tag
|
(defn prop-tag
|
||||||
[props blur?]
|
[props blur?]
|
||||||
[rn/view {:style {:margin-right 4}}
|
[context-tag/view
|
||||||
[context-tag/view (merge props {:size 24 :blur? blur?})]])
|
(assoc props
|
||||||
|
:size 24
|
||||||
|
:blur? blur?
|
||||||
|
:container-style {:flex-shrink 1})])
|
||||||
|
|
||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press
|
[{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press
|
||||||
@@ -121,7 +124,7 @@
|
|||||||
:on-press-out on-press-out}
|
:on-press-out on-press-out}
|
||||||
[rn/view {:style style/container}
|
[rn/view {:style style/container}
|
||||||
[transaction-icon-view props theme]
|
[transaction-icon-view props theme]
|
||||||
[rn/view
|
[rn/view {:style {:flex 1}}
|
||||||
[transaction-header props theme]
|
[transaction-header props theme]
|
||||||
[rn/view {:style style/content-line}
|
[rn/view {:style style/content-line}
|
||||||
(when first-tag [prop-tag first-tag blur?])
|
(when first-tag [prop-tag first-tag blur?])
|
||||||
|
|||||||
@@ -147,6 +147,7 @@
|
|||||||
quo.components.settings.settings-item.view
|
quo.components.settings.settings-item.view
|
||||||
quo.components.share.qr-code.view
|
quo.components.share.qr-code.view
|
||||||
quo.components.share.share-qr-code.view
|
quo.components.share.share-qr-code.view
|
||||||
|
quo.components.slideshow.slider-bar.view
|
||||||
quo.components.switchers.group-messaging-card.view
|
quo.components.switchers.group-messaging-card.view
|
||||||
quo.components.tabs.account-selector
|
quo.components.tabs.account-selector
|
||||||
quo.components.tabs.segmented-tab
|
quo.components.tabs.segmented-tab
|
||||||
@@ -185,6 +186,7 @@
|
|||||||
quo.components.wallet.progress-bar.view
|
quo.components.wallet.progress-bar.view
|
||||||
quo.components.wallet.required-tokens.view
|
quo.components.wallet.required-tokens.view
|
||||||
quo.components.wallet.summary-info.view
|
quo.components.wallet.summary-info.view
|
||||||
|
quo.components.wallet.swap-input.view
|
||||||
quo.components.wallet.token-input.view
|
quo.components.wallet.token-input.view
|
||||||
quo.components.wallet.transaction-progress.view
|
quo.components.wallet.transaction-progress.view
|
||||||
quo.components.wallet.transaction-summary.view
|
quo.components.wallet.transaction-summary.view
|
||||||
@@ -418,6 +420,9 @@
|
|||||||
(def qr-code quo.components.share.qr-code.view/view)
|
(def qr-code quo.components.share.qr-code.view/view)
|
||||||
(def share-qr-code quo.components.share.share-qr-code.view/view)
|
(def share-qr-code quo.components.share.share-qr-code.view/view)
|
||||||
|
|
||||||
|
;;;; Slideshow
|
||||||
|
(def slider-bar quo.components.slideshow.slider-bar.view/view)
|
||||||
|
|
||||||
;;;; SWITCHER
|
;;;; SWITCHER
|
||||||
(def group-messaging-card quo.components.switchers.group-messaging-card.view/view)
|
(def group-messaging-card quo.components.switchers.group-messaging-card.view/view)
|
||||||
|
|
||||||
@@ -468,6 +473,7 @@
|
|||||||
(def progress-bar quo.components.wallet.progress-bar.view/view)
|
(def progress-bar quo.components.wallet.progress-bar.view/view)
|
||||||
(def required-tokens quo.components.wallet.required-tokens.view/view)
|
(def required-tokens quo.components.wallet.required-tokens.view/view)
|
||||||
(def summary-info quo.components.wallet.summary-info.view/view)
|
(def summary-info quo.components.wallet.summary-info.view/view)
|
||||||
|
(def swap-input quo.components.wallet.swap-input.view/view)
|
||||||
(def network-link quo.components.wallet.network-link.view/view)
|
(def network-link quo.components.wallet.network-link.view/view)
|
||||||
(def token-input quo.components.wallet.token-input.view/view)
|
(def token-input quo.components.wallet.token-input.view/view)
|
||||||
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
|
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
|
||||||
|
|||||||
@@ -87,6 +87,7 @@
|
|||||||
quo.components.settings.reorder-item.component-spec
|
quo.components.settings.reorder-item.component-spec
|
||||||
quo.components.settings.settings-item.component-spec
|
quo.components.settings.settings-item.component-spec
|
||||||
quo.components.share.share-qr-code.component-spec
|
quo.components.share.share-qr-code.component-spec
|
||||||
|
quo.components.slideshow.slider-bar.component-spec
|
||||||
quo.components.switchers.base-card.component-spec
|
quo.components.switchers.base-card.component-spec
|
||||||
quo.components.switchers.group-messaging-card.component-spec
|
quo.components.switchers.group-messaging-card.component-spec
|
||||||
quo.components.tags.collectible-tag.component-spec
|
quo.components.tags.collectible-tag.component-spec
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
quo.components.wallet.progress-bar.component-spec
|
quo.components.wallet.progress-bar.component-spec
|
||||||
quo.components.wallet.required-tokens.component-spec
|
quo.components.wallet.required-tokens.component-spec
|
||||||
quo.components.wallet.summary-info.component-spec
|
quo.components.wallet.summary-info.component-spec
|
||||||
|
quo.components.wallet.swap-input.component-spec
|
||||||
quo.components.wallet.token-input.component-spec
|
quo.components.wallet.token-input.component-spec
|
||||||
quo.components.wallet.transaction-progress.component-spec
|
quo.components.wallet.transaction-progress.component-spec
|
||||||
quo.components.wallet.transaction-summary.component-spec
|
quo.components.wallet.transaction-summary.component-spec
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
:gnosis (js/require "../resources/images/networks/Gnosis.png")
|
:gnosis (js/require "../resources/images/networks/Gnosis.png")
|
||||||
:hermez (js/require "../resources/images/networks/Hermez.png")
|
:hermez (js/require "../resources/images/networks/Hermez.png")
|
||||||
:optimism (js/require "../resources/images/networks/Optimism.png")
|
:optimism (js/require "../resources/images/networks/Optimism.png")
|
||||||
|
:paraswap (js/require "../resources/images/networks/Paraswap.png")
|
||||||
:polygon (js/require "../resources/images/networks/Polygon.png")
|
:polygon (js/require "../resources/images/networks/Polygon.png")
|
||||||
:scroll (js/require "../resources/images/networks/Scroll.png")
|
:scroll (js/require "../resources/images/networks/Scroll.png")
|
||||||
:taiko (js/require "../resources/images/networks/Taiko.png")
|
:taiko (js/require "../resources/images/networks/Taiko.png")
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
(oops/ocall wc-utils
|
(oops/ocall wc-utils
|
||||||
"buildApprovedNamespaces"
|
"buildApprovedNamespaces"
|
||||||
(bean/->js {:proposal proposal
|
(bean/->js {:proposal proposal
|
||||||
:supportedNamespaces supported-namespaces})))
|
:supportedNamespaces (clj->js supported-namespaces)})))
|
||||||
|
|
||||||
;; Get an error from this list:
|
;; Get an error from this list:
|
||||||
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts
|
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts
|
||||||
@@ -51,9 +51,10 @@
|
|||||||
|
|
||||||
(defn reject-session
|
(defn reject-session
|
||||||
[{:keys [web3-wallet id reason]}]
|
[{:keys [web3-wallet id reason]}]
|
||||||
(.rejectSession web3-wallet
|
(oops/ocall web3-wallet
|
||||||
(clj->js {:id id
|
"rejectSession"
|
||||||
:reason reason})))
|
(bean/->js {:id id
|
||||||
|
:reason reason})))
|
||||||
|
|
||||||
(defn approve-session
|
(defn approve-session
|
||||||
[{:keys [web3-wallet id approved-namespaces]}]
|
[{:keys [web3-wallet id approved-namespaces]}]
|
||||||
@@ -62,16 +63,17 @@
|
|||||||
(bean/->js {:id id
|
(bean/->js {:id id
|
||||||
:namespaces approved-namespaces})))
|
:namespaces approved-namespaces})))
|
||||||
|
|
||||||
|
(defn disconnect-session
|
||||||
|
[{:keys [web3-wallet reason topic]}]
|
||||||
|
(oops/ocall web3-wallet
|
||||||
|
"disconnectSession"
|
||||||
|
(bean/->js {:topic topic
|
||||||
|
:reason reason})))
|
||||||
|
|
||||||
(defn get-active-sessions
|
(defn get-active-sessions
|
||||||
[web3-wallet]
|
[web3-wallet]
|
||||||
(oops/ocall web3-wallet "getActiveSessions"))
|
(oops/ocall web3-wallet "getActiveSessions"))
|
||||||
|
|
||||||
(defn core-pairing-disconnnect
|
|
||||||
[web3-wallet topic]
|
|
||||||
(oops/ocall web3-wallet
|
|
||||||
"core.pairing.disconnect"
|
|
||||||
(bean/->js {:topic topic})))
|
|
||||||
|
|
||||||
(defn core-pairing-pair
|
(defn core-pairing-pair
|
||||||
[web3-wallet url]
|
[web3-wallet url]
|
||||||
(oops/ocall web3-wallet
|
(oops/ocall web3-wallet
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
(ns status-im.common.floating-button-page.floating-container.style
|
(ns status-im.common.floating-button-page.floating-container.style
|
||||||
(:require [react-native.safe-area :as safe-area]))
|
(:require [quo.foundations.colors :as colors]
|
||||||
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
(defn content-container
|
(defn content-container
|
||||||
[blur? keyboard-shown?]
|
[blur? keyboard-shown?]
|
||||||
@@ -11,7 +12,12 @@
|
|||||||
:padding-horizontal 20}
|
:padding-horizontal 20}
|
||||||
blur? (dissoc :padding-vertical :padding-horizontal))))
|
blur? (dissoc :padding-vertical :padding-horizontal))))
|
||||||
|
|
||||||
(def blur-inner-container
|
(defn blur-inner-container
|
||||||
{:background-color :transparent ; required, otherwise blur-view will shrink
|
[theme shell-overlay?]
|
||||||
|
{:background-color (colors/theme-colors colors/white-70-blur
|
||||||
|
(if shell-overlay?
|
||||||
|
colors/neutral-80-opa-80-blur
|
||||||
|
colors/neutral-95-opa-70-blur)
|
||||||
|
theme)
|
||||||
:padding-vertical 12
|
:padding-vertical 12
|
||||||
:padding-horizontal 20})
|
:padding-horizontal 20})
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
(ns status-im.common.floating-button-page.floating-container.view
|
(ns status-im.common.floating-button-page.floating-container.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.foundations.colors :as colors]
|
|
||||||
[quo.theme :as quo.theme]
|
[quo.theme :as quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im.common.floating-button-page.floating-container.style :as style]))
|
[status-im.common.floating-button-page.floating-container.style :as style]))
|
||||||
|
|
||||||
(defn- blur-container
|
(defn- blur-container
|
||||||
[child]
|
[child shell-overlay?]
|
||||||
(let [theme (quo.theme/use-theme)]
|
(let [theme (quo.theme/use-theme)]
|
||||||
[quo/blur
|
[quo/blur
|
||||||
{:blur-amount 52
|
{:blur-amount 20
|
||||||
:blur-radius 20
|
:blur-type :transparent
|
||||||
:blur-type :transparent
|
:overlay-color :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 theme shell-overlay?)}
|
||||||
[rn/view {:style style/blur-inner-container}
|
|
||||||
child]]))
|
child]]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [on-layout keyboard-shown? blur?]} child]
|
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (style/content-container blur? keyboard-shown?)
|
{:style (style/content-container blur? keyboard-shown?)
|
||||||
:on-layout on-layout}
|
:on-layout on-layout}
|
||||||
(if blur?
|
(if blur?
|
||||||
[blur-container child]
|
[blur-container child shell-overlay?]
|
||||||
child)])
|
child)])
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [header footer customization-color footer-container-padding header-container-style
|
[{:keys [header footer customization-color footer-container-padding header-container-style
|
||||||
content-container-style gradient-cover? keyboard-should-persist-taps]
|
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
|
||||||
:or {footer-container-padding (safe-area/get-top)}}
|
:or {footer-container-padding (safe-area/get-top)}}
|
||||||
& children]
|
& children]
|
||||||
(reagent/with-let [scroll-view-ref (atom nil)
|
(reagent/with-let [scroll-view-ref (atom nil)
|
||||||
@@ -121,7 +121,8 @@
|
|||||||
[floating-container/view
|
[floating-container/view
|
||||||
{:on-layout set-footer-container-height
|
{:on-layout set-footer-container-height
|
||||||
:keyboard-shown? keyboard-shown?
|
:keyboard-shown? keyboard-shown?
|
||||||
:blur? show-background?}
|
:blur? show-background?
|
||||||
|
:shell-overlay? shell-overlay?}
|
||||||
footer]]]])
|
footer]]]])
|
||||||
(finally
|
(finally
|
||||||
(remove-listeners))))
|
(remove-listeners))))
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
(ns status-im.common.metrics-confirmation-modal.style)
|
||||||
|
|
||||||
|
(def points-wrapper
|
||||||
|
{:margin-top 11
|
||||||
|
:margin-horizontal 20
|
||||||
|
:gap 21
|
||||||
|
:margin-bottom 15})
|
||||||
|
|
||||||
|
(def item-text
|
||||||
|
{:margin-top 10
|
||||||
|
:margin-left -4})
|
||||||
|
|
||||||
|
(def info-text
|
||||||
|
{:margin-top -5})
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
(ns status-im.common.metrics-confirmation-modal.view
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im.common.metrics-confirmation-modal.style :as style]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(defn- dismiss-keyboard
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:dismiss-keyboard]))
|
||||||
|
|
||||||
|
(defn- hide-bottom-sheet
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:hide-bottom-sheet]))
|
||||||
|
|
||||||
|
(defn- toggle-metrics
|
||||||
|
[enabled?]
|
||||||
|
(rf/dispatch [:centralized-metrics/toggle-centralized-metrics enabled?]))
|
||||||
|
|
||||||
|
(def ^:private will-receive-points
|
||||||
|
[:t/ip-address
|
||||||
|
:t/universally-unique-identifiers-of-device
|
||||||
|
:t/logs-of-actions-withing-the-app])
|
||||||
|
|
||||||
|
(def ^:private not-receive-points
|
||||||
|
[:t/your-profile-information
|
||||||
|
:t/your-addresses
|
||||||
|
:t/information-you-input-and-send])
|
||||||
|
|
||||||
|
(defn- bullet-points
|
||||||
|
[{:keys [title points]}]
|
||||||
|
[rn/view
|
||||||
|
[quo/text {:weight :semi-bold}
|
||||||
|
title]
|
||||||
|
(for [label points]
|
||||||
|
^{:key label}
|
||||||
|
[quo/markdown-list
|
||||||
|
{:description (i18n/label label)
|
||||||
|
:blur? true
|
||||||
|
:container-style style/item-text}])])
|
||||||
|
|
||||||
|
(defn- on-share-usage
|
||||||
|
[]
|
||||||
|
(toggle-metrics true)
|
||||||
|
(hide-bottom-sheet))
|
||||||
|
|
||||||
|
(defn- on-do-not-share
|
||||||
|
[]
|
||||||
|
(toggle-metrics false)
|
||||||
|
(hide-bottom-sheet))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[{:keys [settings?]}]
|
||||||
|
(rn/use-mount #(dismiss-keyboard))
|
||||||
|
[:<>
|
||||||
|
[quo/drawer-top
|
||||||
|
{:title (i18n/label :t/help-us-improve-status)
|
||||||
|
:description (i18n/label :t/collecting-usage-data)}]
|
||||||
|
[rn/view {:style style/points-wrapper}
|
||||||
|
[bullet-points
|
||||||
|
{:title (i18n/label :t/what-we-will-receive)
|
||||||
|
:points will-receive-points}]
|
||||||
|
[bullet-points
|
||||||
|
{:title (i18n/label :t/what-we-wont-receive)
|
||||||
|
:points not-receive-points}]
|
||||||
|
(when-not settings?
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style style/info-text}
|
||||||
|
(i18n/label :t/sharing-usage-data-can-be-turned-off)])]
|
||||||
|
[quo/bottom-actions
|
||||||
|
{:actions :two-actions
|
||||||
|
:blur? true
|
||||||
|
:button-one-label (i18n/label :t/share-usage-data)
|
||||||
|
:button-one-props {:on-press on-share-usage}
|
||||||
|
:button-two-label (i18n/label (if settings? :t/do-not-share :t/not-now))
|
||||||
|
:button-two-props {:type :grey
|
||||||
|
:on-press on-do-not-share}}]])
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
(ns status-im.common.new-device-sheet.style
|
||||||
|
(:require [quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def heading
|
||||||
|
{:padding-left 20
|
||||||
|
:padding-bottom 8})
|
||||||
|
|
||||||
|
(def message
|
||||||
|
{:padding-horizontal 20
|
||||||
|
:padding-top 4})
|
||||||
|
|
||||||
|
(def warning
|
||||||
|
{:margin-horizontal 20
|
||||||
|
:margin-top 10})
|
||||||
|
|
||||||
|
(def drawer-container
|
||||||
|
{:padding-horizontal 13
|
||||||
|
:padding-top 16})
|
||||||
|
|
||||||
|
(def settings-subtext
|
||||||
|
{:color colors/white-opa-70
|
||||||
|
:align-self :center
|
||||||
|
:margin-bottom 12})
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
(ns status-im.common.new-device-sheet.view
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[status-im.common.new-device-sheet.style :as style]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(defn- dismiss-keyboard
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:dismiss-keyboard]))
|
||||||
|
|
||||||
|
(defn- hide-bottom-sheet
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:hide-bottom-sheet]))
|
||||||
|
|
||||||
|
(defn- pair-and-sync
|
||||||
|
[installation-id]
|
||||||
|
(rf/dispatch [:pairing/pair-and-sync installation-id])
|
||||||
|
(hide-bottom-sheet))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[installation-id]
|
||||||
|
(dismiss-keyboard)
|
||||||
|
[:<>
|
||||||
|
[quo/text
|
||||||
|
{:weight :semi-bold
|
||||||
|
:size :heading-2
|
||||||
|
:accessibility-label :new-device-sheet-heading
|
||||||
|
:style style/heading}
|
||||||
|
(i18n/label :t/pair-new-device-and-sync)]
|
||||||
|
[quo/text
|
||||||
|
{:weight :regular
|
||||||
|
:size :paragraph-1
|
||||||
|
:accessibility-label :new-device-sheet-message
|
||||||
|
:style style/message}
|
||||||
|
(i18n/label :t/new-device-detected)]
|
||||||
|
[quo/text
|
||||||
|
{:weight :semi-bold
|
||||||
|
:size :heading-2
|
||||||
|
:accessibility-label :new-device-installation-id
|
||||||
|
:style style/heading}
|
||||||
|
installation-id]
|
||||||
|
[quo/bottom-actions
|
||||||
|
{:actions :two-actions
|
||||||
|
:blur? true
|
||||||
|
:container-style {:margin-top 12}
|
||||||
|
:button-two-label (i18n/label :t/cancel)
|
||||||
|
:button-two-props {:type :grey
|
||||||
|
:on-press hide-bottom-sheet}
|
||||||
|
:button-one-label (i18n/label :t/pair-and-sync)
|
||||||
|
:button-one-props {:on-press #(pair-and-sync installation-id)}}]])
|
||||||
|
|
||||||
|
(defn view-2
|
||||||
|
[]
|
||||||
|
(let [installation-id (rf/sub [:profile/installation-id])]
|
||||||
|
(dismiss-keyboard)
|
||||||
|
[:<>
|
||||||
|
[quo/text
|
||||||
|
{:weight :semi-bold
|
||||||
|
:size :heading-2
|
||||||
|
:accessibility-label :new-device-sheet-heading
|
||||||
|
:style style/heading}
|
||||||
|
(i18n/label :t/pair-new-device-and-sync)]
|
||||||
|
[quo/text
|
||||||
|
{:weight :regular
|
||||||
|
:size :paragraph-1
|
||||||
|
:accessibility-label :new-device-sheet-message
|
||||||
|
:style style/message}
|
||||||
|
(i18n/label :t/check-new-device)]
|
||||||
|
[quo/text
|
||||||
|
{:weight :semi-bold
|
||||||
|
:size :heading-2
|
||||||
|
:accessibility-label :new-device-installation-id
|
||||||
|
:style style/heading}
|
||||||
|
installation-id]
|
||||||
|
[quo/bottom-actions
|
||||||
|
{:actions :one-action
|
||||||
|
:blur? true
|
||||||
|
:container-style {:margin-top 12}
|
||||||
|
:button-one-label (i18n/label :t/close)
|
||||||
|
:button-one-props {:type :grey
|
||||||
|
:on-press hide-bottom-sheet}}]]))
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
;; CONFIG VALUES
|
;; CONFIG VALUES
|
||||||
(def log-level (string/upper-case (get-config :LOG_LEVEL "")))
|
(def log-level (string/upper-case (get-config :LOG_LEVEL "")))
|
||||||
(def fleet (get-config :FLEET "waku.sandbox"))
|
(def fleet (get-config :FLEET ""))
|
||||||
(def apn-topic (get-config :APN_TOPIC "im.status.ethereum"))
|
(def apn-topic (get-config :APN_TOPIC "im.status.ethereum"))
|
||||||
(def default-network (get-config :DEFAULT_NETWORK "goerli_rpc"))
|
(def default-network (get-config :DEFAULT_NETWORK "goerli_rpc"))
|
||||||
(def max-installations 2)
|
(def max-installations 2)
|
||||||
|
|||||||
@@ -45,6 +45,11 @@
|
|||||||
(def ^:const activity-center-membership-status-accepted 2)
|
(def ^:const activity-center-membership-status-accepted 2)
|
||||||
(def ^:const activity-center-membership-status-declined 3)
|
(def ^:const activity-center-membership-status-declined 3)
|
||||||
|
|
||||||
|
;; Choose the maximum number of notifications that *usually/safely* fit on
|
||||||
|
;; most screens, so that the UI doesn't have to needlessly render
|
||||||
|
;; notifications.
|
||||||
|
(def ^:const notifications-per-page 7)
|
||||||
|
|
||||||
(def ^:const mute-for-15-mins-type 1)
|
(def ^:const mute-for-15-mins-type 1)
|
||||||
(def ^:const mute-for-1-hour-type 2)
|
(def ^:const mute-for-1-hour-type 2)
|
||||||
(def ^:const mute-for-8-hours-type 3)
|
(def ^:const mute-for-8-hours-type 3)
|
||||||
@@ -276,16 +281,21 @@
|
|||||||
#{wallet-connect-personal-sign-method
|
#{wallet-connect-personal-sign-method
|
||||||
wallet-connect-eth-sign-method
|
wallet-connect-eth-sign-method
|
||||||
wallet-connect-eth-send-transaction-method
|
wallet-connect-eth-send-transaction-method
|
||||||
wallet-connect-eth-sign-transaction-method
|
;; NOTE: disabled, as we have no clear use cases for it and other wallets don't support it
|
||||||
|
;; wallet-connect-eth-sign-transaction-method
|
||||||
wallet-connect-eth-sign-typed-method
|
wallet-connect-eth-sign-typed-method
|
||||||
wallet-connect-eth-sign-typed-v4-method})
|
wallet-connect-eth-sign-typed-v4-method})
|
||||||
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
|
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
|
||||||
(def ^:const wallet-connect-session-proposal-event "session_proposal")
|
(def ^:const wallet-connect-session-proposal-event "session_proposal")
|
||||||
(def ^:const wallet-connect-session-request-event "session_request")
|
(def ^:const wallet-connect-session-request-event "session_request")
|
||||||
|
(def ^:const wallet-connect-session-delete-event "session_delete")
|
||||||
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
|
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
|
||||||
|
(def ^:const wallet-connect-user-disconnected-reason-key "USER_DISCONNECTED")
|
||||||
|
|
||||||
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
|
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
|
||||||
|
|
||||||
|
(def ^:const token-sort-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3})
|
||||||
|
|
||||||
(def ^:const dapp-permission-contact-code "contact-code")
|
(def ^:const dapp-permission-contact-code "contact-code")
|
||||||
(def ^:const dapp-permission-web3 "web3")
|
(def ^:const dapp-permission-web3 "web3")
|
||||||
(def ^:const dapp-permission-qr-code "qr-code")
|
(def ^:const dapp-permission-qr-code "qr-code")
|
||||||
@@ -506,6 +516,9 @@
|
|||||||
(def ^:const optimism-full-name "Optimism")
|
(def ^:const optimism-full-name "Optimism")
|
||||||
(def ^:const arbitrum-full-name "Arbitrum")
|
(def ^:const arbitrum-full-name "Arbitrum")
|
||||||
|
|
||||||
|
(def ^:const sepolia-full-name "Sepolia")
|
||||||
|
(def ^:const goerli-full-name "Goerli")
|
||||||
|
|
||||||
(def ^:const mainnet-network-name :mainnet)
|
(def ^:const mainnet-network-name :mainnet)
|
||||||
(def ^:const ethereum-network-name :ethereum)
|
(def ^:const ethereum-network-name :ethereum)
|
||||||
(def ^:const optimism-network-name :optimism)
|
(def ^:const optimism-network-name :optimism)
|
||||||
@@ -567,5 +580,8 @@
|
|||||||
(def ^:const max-recommended-slippage 5)
|
(def ^:const max-recommended-slippage 5)
|
||||||
(def ^:const max-slippage-decimal-places 2)
|
(def ^:const max-slippage-decimal-places 2)
|
||||||
(def ^:const swap-default-provider
|
(def ^:const swap-default-provider
|
||||||
{:name "Paraswap"
|
{:name :paraswap
|
||||||
|
:full-name "Paraswap"
|
||||||
|
:color :blue
|
||||||
|
:contract-address "0xdef171fe48cf0115b1d80b88dc8eab59176fee57"
|
||||||
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
|
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
|
||||||
|
|||||||
@@ -7,10 +7,17 @@
|
|||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(def ^:const user-confirmed-key :centralized-metrics/user-confirmed?)
|
||||||
|
(def ^:const enabled-key :centralized-metrics/enabled?)
|
||||||
|
|
||||||
|
(defn show-confirmation-modal?
|
||||||
|
[db]
|
||||||
|
(not (user-confirmed-key db)))
|
||||||
|
|
||||||
(defn push-event?
|
(defn push-event?
|
||||||
[db]
|
[db]
|
||||||
(or (not (:centralized-metrics/user-confirmed? db))
|
(or (not (user-confirmed-key db))
|
||||||
(:centralized-metrics/enabled? db)))
|
(enabled-key db)))
|
||||||
|
|
||||||
(defn centralized-metrics-interceptor
|
(defn centralized-metrics-interceptor
|
||||||
[context]
|
[context]
|
||||||
@@ -29,5 +36,16 @@
|
|||||||
(fn [{:keys [db]} [enabled?]]
|
(fn [{:keys [db]} [enabled?]]
|
||||||
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
|
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
|
||||||
:db (assoc db
|
:db (assoc db
|
||||||
:centralized-metrics/user-confirmed? true
|
user-confirmed-key
|
||||||
:centralized-metrics/enabled? enabled?)}))
|
true
|
||||||
|
enabled-key
|
||||||
|
enabled?)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :centralized-metrics/check-modal
|
||||||
|
(fn [{:keys [db]} [modal-view]]
|
||||||
|
(when (show-confirmation-modal? db)
|
||||||
|
{:fx [[:dispatch
|
||||||
|
[:show-bottom-sheet
|
||||||
|
{:content (fn [] [modal-view])
|
||||||
|
:shell? true}]]]})))
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
||||||
[test-helpers.unit :as h]))
|
[test-helpers.unit :as h]))
|
||||||
|
|
||||||
|
(deftest show-confirmation-modal-test
|
||||||
|
(testing "returns true if the user confirmed"
|
||||||
|
(is (false? (events/show-confirmation-modal? {events/user-confirmed-key true})))
|
||||||
|
(is (true? (events/show-confirmation-modal? {})))))
|
||||||
|
|
||||||
(deftest push-event-test
|
(deftest push-event-test
|
||||||
(testing "returns correct boolean value"
|
(testing "returns correct boolean value"
|
||||||
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
|
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
:on-error #(p-reject (str "failed to sign data\n" %))}))))
|
:on-error #(p-reject (str "failed to sign data\n" %))}))))
|
||||||
|
|
||||||
(defn- edit-shared-addresses-for-community
|
(defn- edit-shared-addresses-for-community
|
||||||
[community-id signatures addresses-to-reveal airdrop-address]
|
[community-id signatures addresses-to-reveal airdrop-address _share-future-addresses?]
|
||||||
(promesa/create
|
(promesa/create
|
||||||
(fn [p-resolve p-reject]
|
(fn [p-resolve p-reject]
|
||||||
(rpc/call
|
(rpc/call
|
||||||
@@ -41,15 +41,16 @@
|
|||||||
:on-error p-reject}))))
|
:on-error p-reject}))))
|
||||||
|
|
||||||
(defn- request-to-join
|
(defn- request-to-join
|
||||||
[community-id signatures addresses-to-reveal airdrop-address]
|
[community-id signatures addresses-to-reveal airdrop-address share-future-addresses?]
|
||||||
(promesa/create
|
(promesa/create
|
||||||
(fn [p-resolve p-reject]
|
(fn [p-resolve p-reject]
|
||||||
(rpc/call
|
(rpc/call
|
||||||
{:method :wakuext_requestToJoinCommunity
|
{:method :wakuext_requestToJoinCommunity
|
||||||
:params [{:communityId community-id
|
:params [{:communityId community-id
|
||||||
:signatures signatures
|
:signatures signatures
|
||||||
:addressesToReveal addresses-to-reveal
|
:addressesToReveal addresses-to-reveal
|
||||||
:airdropAddress airdrop-address}]
|
:airdropAddress airdrop-address
|
||||||
|
:shareFutureAddresses share-future-addresses?}]
|
||||||
:js-response true
|
:js-response true
|
||||||
:on-success p-resolve
|
:on-success p-resolve
|
||||||
:on-error p-reject}))))
|
:on-error p-reject}))))
|
||||||
@@ -64,15 +65,18 @@
|
|||||||
|
|
||||||
(defn- sign-and-call-endpoint
|
(defn- sign-and-call-endpoint
|
||||||
[{:keys [community-id password pub-key
|
[{:keys [community-id password pub-key
|
||||||
addresses-to-reveal airdrop-address
|
addresses-to-reveal airdrop-address share-future-addresses?
|
||||||
on-success on-error
|
on-success on-error
|
||||||
callback]}]
|
callback]}]
|
||||||
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key community-id addresses-to-reveal)
|
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key
|
||||||
|
community-id
|
||||||
|
addresses-to-reveal)
|
||||||
signatures (sign-data sign-params password)
|
signatures (sign-data sign-params password)
|
||||||
result (callback community-id
|
result (callback community-id
|
||||||
signatures
|
signatures
|
||||||
addresses-to-reveal
|
addresses-to-reveal
|
||||||
airdrop-address)]
|
airdrop-address
|
||||||
|
share-future-addresses?)]
|
||||||
(run-callback-or-event on-success result))
|
(run-callback-or-event on-success result))
|
||||||
(promesa/catch #(run-callback-or-event on-error %))))
|
(promesa/catch #(run-callback-or-event on-error %))))
|
||||||
|
|
||||||
@@ -87,6 +91,7 @@
|
|||||||
[:or [:set string?]
|
[:or [:set string?]
|
||||||
[:sequential string?]]]
|
[:sequential string?]]]
|
||||||
[:airdrop-address string?]
|
[:airdrop-address string?]
|
||||||
|
[:share-future-addresses? boolean?]
|
||||||
[:on-success [:or fn? :schema.re-frame/event]]
|
[:on-success [:or fn? :schema.re-frame/event]]
|
||||||
[:on-error [:or fn? :schema.re-frame/event]]
|
[:on-error [:or fn? :schema.re-frame/event]]
|
||||||
[:callback fn?]]]
|
[:callback fn?]]]
|
||||||
|
|||||||
@@ -17,13 +17,12 @@
|
|||||||
(rf/reg-event-fx :communities/initialize-permission-addresses initialize-permission-addresses)
|
(rf/reg-event-fx :communities/initialize-permission-addresses initialize-permission-addresses)
|
||||||
|
|
||||||
(defn do-init-permission-addresses
|
(defn do-init-permission-addresses
|
||||||
[{:keys [db]} [community-id revealed-accounts]]
|
[{:keys [db]} [community-id revealed-accounts share-future-addresses?]]
|
||||||
(let [wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
|
(let [wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
|
||||||
addresses-to-reveal (if (seq revealed-accounts)
|
addresses-to-reveal (if (seq revealed-accounts)
|
||||||
(set (keys revealed-accounts))
|
(set (keys revealed-accounts))
|
||||||
;; Reveal all addresses as fallback.
|
;; Reveal all addresses as fallback.
|
||||||
(set (map :address wallet-accounts)))
|
(set (map :address wallet-accounts)))
|
||||||
|
|
||||||
;; When there are no revealed addresses, such as when joining a
|
;; When there are no revealed addresses, such as when joining a
|
||||||
;; community, use first address for airdrops.
|
;; community, use first address for airdrops.
|
||||||
airdrop-address (or (->> revealed-accounts
|
airdrop-address (or (->> revealed-accounts
|
||||||
@@ -35,10 +34,7 @@
|
|||||||
first
|
first
|
||||||
:address))]
|
:address))]
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
;; Set to false by default while we don't persist the user's choice
|
(assoc-in [:communities/selected-share-all-addresses community-id] share-future-addresses?)
|
||||||
;; in status-go, otherwise whenever the view is mounted, the choice
|
|
||||||
;; of selected addresses won't be respected.
|
|
||||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
|
||||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
||||||
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
||||||
:fx [[:dispatch
|
:fx [[:dispatch
|
||||||
@@ -60,36 +56,44 @@
|
|||||||
is selecting an airdrop address, we must submit to status-go the current
|
is selecting an airdrop address, we must submit to status-go the current
|
||||||
choice of addresses to share, and vice-versa. If we omit addresses to share,
|
choice of addresses to share, and vice-versa. If we omit addresses to share,
|
||||||
status-go will default to all available."
|
status-go will default to all available."
|
||||||
[{:keys [db]} [{:keys [community-id password on-success addresses airdrop-address]}]]
|
[{:keys [db]}
|
||||||
(let [pub-key (get-in db [:profile/profile :public-key])
|
[{:keys [community-id password on-success addresses airdrop-address share-future-addresses?]}]]
|
||||||
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
|
(let [pub-key (get-in db [:profile/profile :public-key])
|
||||||
addresses-to-reveal (if (seq addresses)
|
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
|
||||||
(set addresses)
|
addresses-to-reveal (if (seq addresses)
|
||||||
(get-in db [:communities/all-addresses-to-reveal community-id]))
|
(set addresses)
|
||||||
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
|
(get-in db [:communities/all-addresses-to-reveal community-id]))
|
||||||
airdrop-address
|
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
|
||||||
(->> wallet-accounts
|
airdrop-address
|
||||||
(filter #(contains? addresses-to-reveal (:address %)))
|
(->> wallet-accounts
|
||||||
first
|
(filter #(contains? addresses-to-reveal (:address %)))
|
||||||
:address))]
|
first
|
||||||
|
:address))
|
||||||
|
share-future-addresses? (if (nil? share-future-addresses?)
|
||||||
|
(get-in db [:communities/selected-share-all-addresses community-id])
|
||||||
|
share-future-addresses?)]
|
||||||
{:fx [[:effects.community/edit-shared-addresses
|
{:fx [[:effects.community/edit-shared-addresses
|
||||||
{:community-id community-id
|
{:community-id community-id
|
||||||
:password password
|
:password password
|
||||||
:pub-key pub-key
|
:pub-key pub-key
|
||||||
:addresses-to-reveal addresses-to-reveal
|
:addresses-to-reveal addresses-to-reveal
|
||||||
:airdrop-address new-airdrop-address
|
:share-future-addresses? share-future-addresses?
|
||||||
:on-success (fn []
|
:airdrop-address new-airdrop-address
|
||||||
(when (fn? on-success)
|
:on-success (fn []
|
||||||
(on-success addresses-to-reveal new-airdrop-address))
|
(when (fn? on-success)
|
||||||
(rf/dispatch [:communities/edit-shared-addresses-success
|
(on-success addresses-to-reveal
|
||||||
community-id addresses-to-reveal airdrop-address]))
|
new-airdrop-address
|
||||||
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
|
share-future-addresses?))
|
||||||
|
(rf/dispatch [:communities/edit-shared-addresses-success
|
||||||
|
community-id addresses-to-reveal airdrop-address]))
|
||||||
|
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/edit-shared-addresses edit-shared-addresses)
|
(rf/reg-event-fx :communities/edit-shared-addresses edit-shared-addresses)
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/edit-shared-addresses-success
|
(rf/reg-event-fx :communities/edit-shared-addresses-success
|
||||||
(fn [_ [community-id addresses-to-reveal airdrop-address]]
|
(fn [_ [community-id addresses-to-reveal airdrop-address share-future-addresses?]]
|
||||||
{:fx [[:dispatch [:communities/set-airdrop-address community-id airdrop-address]]
|
{:fx [[:dispatch [:communities/set-airdrop-address community-id airdrop-address]]
|
||||||
|
[:dispatch [:communities/set-share-all-addresses community-id share-future-addresses?]]
|
||||||
[:dispatch [:communities/set-addresses-to-reveal community-id addresses-to-reveal]]]}))
|
[:dispatch [:communities/set-addresses-to-reveal community-id addresses-to-reveal]]]}))
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/edit-shared-addresses-failure
|
(rf/reg-event-fx :communities/edit-shared-addresses-failure
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
(is
|
(is
|
||||||
(match?
|
(match?
|
||||||
{:db (-> (:db cofx)
|
{:db (-> (:db cofx)
|
||||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
(assoc-in [:communities/selected-share-all-addresses community-id] true)
|
||||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
||||||
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
||||||
:fx [[:dispatch
|
:fx [[:dispatch
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
[:dispatch
|
[:dispatch
|
||||||
[:communities/check-permissions-to-join-during-selection community-id
|
[:communities/check-permissions-to-join-during-selection community-id
|
||||||
addresses-to-reveal]]]}
|
addresses-to-reveal]]]}
|
||||||
(sut/do-init-permission-addresses cofx [community-id revealed-accounts])))))
|
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true])))))
|
||||||
|
|
||||||
;; Expect to mark all addresses to be revealed and first one to receive
|
;; Expect to mark all addresses to be revealed and first one to receive
|
||||||
;; airdrops when no addresses were previously revealed.
|
;; airdrops when no addresses were previously revealed.
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
(is
|
(is
|
||||||
(match?
|
(match?
|
||||||
{:db (-> (:db cofx)
|
{:db (-> (:db cofx)
|
||||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
(assoc-in [:communities/selected-share-all-addresses community-id] true)
|
||||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
|
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
|
||||||
:fx [[:dispatch
|
:fx [[:dispatch
|
||||||
[:communities/check-permissions-to-join-community
|
[:communities/check-permissions-to-join-community
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
[:dispatch
|
[:dispatch
|
||||||
[:communities/check-permissions-to-join-during-selection community-id
|
[:communities/check-permissions-to-join-during-selection community-id
|
||||||
addresses-to-reveal]]]}
|
addresses-to-reveal]]]}
|
||||||
(sut/do-init-permission-addresses cofx [community-id revealed-accounts]))))))
|
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true]))))))
|
||||||
|
|
||||||
(deftest edit-shared-addresses-test
|
(deftest edit-shared-addresses-test
|
||||||
(testing
|
(testing
|
||||||
@@ -109,6 +109,7 @@
|
|||||||
fallback to all wallet addresses"
|
fallback to all wallet addresses"
|
||||||
(let [pub-key "abcdef"
|
(let [pub-key "abcdef"
|
||||||
revealed-addresses #{"0xB" "0xC"}
|
revealed-addresses #{"0xB" "0xC"}
|
||||||
|
share-future-addresses? true
|
||||||
cofx {:db {:profile/profile {:public-key pub-key}
|
cofx {:db {:profile/profile {:public-key pub-key}
|
||||||
:communities/all-addresses-to-reveal {community-id revealed-addresses}}}
|
:communities/all-addresses-to-reveal {community-id revealed-addresses}}}
|
||||||
airdrop-address "0xB"
|
airdrop-address "0xB"
|
||||||
@@ -116,22 +117,24 @@
|
|||||||
actual
|
actual
|
||||||
(sut/edit-shared-addresses
|
(sut/edit-shared-addresses
|
||||||
cofx
|
cofx
|
||||||
[{:community-id community-id
|
[{:community-id community-id
|
||||||
:password password
|
:password password
|
||||||
:airdrop-address airdrop-address
|
:airdrop-address airdrop-address
|
||||||
:on-success (fn [new-addresses-to-reveal]
|
:share-future-addresses? share-future-addresses?
|
||||||
(is (match? revealed-addresses new-addresses-to-reveal)))}])
|
:on-success (fn [new-addresses-to-reveal]
|
||||||
|
(is (match? revealed-addresses new-addresses-to-reveal)))}])
|
||||||
|
|
||||||
on-success-wrapper (-> actual :fx first second :on-success)]
|
on-success-wrapper (-> actual :fx first second :on-success)]
|
||||||
(is (match?
|
(is (match?
|
||||||
{:fx [[:effects.community/edit-shared-addresses
|
{:fx [[:effects.community/edit-shared-addresses
|
||||||
{:community-id community-id
|
{:community-id community-id
|
||||||
:password password
|
:password password
|
||||||
:pub-key pub-key
|
:pub-key pub-key
|
||||||
:addresses-to-reveal revealed-addresses
|
:addresses-to-reveal revealed-addresses
|
||||||
:airdrop-address airdrop-address
|
:share-future-addresses? share-future-addresses?
|
||||||
:on-success fn?
|
:airdrop-address airdrop-address
|
||||||
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
|
:on-success fn?
|
||||||
|
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
|
||||||
actual))
|
actual))
|
||||||
|
|
||||||
(on-success-wrapper)))
|
(on-success-wrapper)))
|
||||||
|
|||||||
@@ -203,7 +203,9 @@
|
|||||||
:addresses-for-permissions])
|
:addresses-for-permissions])
|
||||||
(rf/dispatch [:hide-bottom-sheet]))}]))}])
|
(rf/dispatch [:hide-bottom-sheet]))}]))}])
|
||||||
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses]))
|
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses]))
|
||||||
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal])))
|
(do
|
||||||
|
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses])
|
||||||
|
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal]))))
|
||||||
highest-role (rf/sub [:communities/highest-role-for-selection id])
|
highest-role (rf/sub [:communities/highest-role-for-selection id])
|
||||||
[unmodified-role _] (rn/use-state highest-role)]
|
[unmodified-role _] (rn/use-state highest-role)]
|
||||||
|
|
||||||
@@ -260,7 +262,8 @@
|
|||||||
|
|
||||||
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
|
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
|
||||||
|
|
||||||
wallet-accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])
|
wallet-accounts (rf/sub [:wallet/operable-accounts])
|
||||||
|
joined (rf/sub [:communities/community-joined id])
|
||||||
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
|
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
|
||||||
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)
|
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)
|
||||||
|
|
||||||
@@ -285,7 +288,6 @@
|
|||||||
(set-flag-share-all-addresses new-value)
|
(set-flag-share-all-addresses new-value)
|
||||||
(when new-value
|
(when new-value
|
||||||
(set-addresses-to-reveal (set (map :address wallet-accounts))))))]
|
(set-addresses-to-reveal (set (map :address wallet-accounts))))))]
|
||||||
|
|
||||||
(rn/use-mount
|
(rn/use-mount
|
||||||
(fn []
|
(fn []
|
||||||
(when-not flag-share-all-addresses
|
(when-not flag-share-all-addresses
|
||||||
@@ -310,6 +312,7 @@
|
|||||||
flag-share-all-addresses]
|
flag-share-all-addresses]
|
||||||
:header [quo/page-setting
|
:header [quo/page-setting
|
||||||
{:checked? flag-share-all-addresses
|
{:checked? flag-share-all-addresses
|
||||||
|
:disabled? joined
|
||||||
:customization-color color
|
:customization-color color
|
||||||
:on-change toggle-flag-share-all-addresses
|
:on-change toggle-flag-share-all-addresses
|
||||||
:setting-text (i18n/label
|
:setting-text (i18n/label
|
||||||
|
|||||||
@@ -47,12 +47,11 @@
|
|||||||
:label (i18n/label :t/view-token-gating)}))
|
:label (i18n/label :t/view-token-gating)}))
|
||||||
|
|
||||||
(defn- action-mark-as-read
|
(defn- action-mark-as-read
|
||||||
[]
|
[chat-id]
|
||||||
(when config/show-not-implemented-features?
|
{:icon :i/mark-as-read
|
||||||
{:icon :i/mark-as-read
|
:accessibility-label :chat-mark-as-read
|
||||||
:accessibility-label :chat-mark-as-read
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-pressed chat-id])
|
||||||
:on-press not-implemented/alert
|
:label (i18n/label :t/mark-as-read)})
|
||||||
:label (i18n/label :t/mark-as-read)}))
|
|
||||||
|
|
||||||
(defn- action-toggle-muted
|
(defn- action-toggle-muted
|
||||||
[id muted? muted-till chat-type]
|
[id muted? muted-till chat-type]
|
||||||
@@ -130,7 +129,7 @@
|
|||||||
(and (not inside-chat?) (not locked?))
|
(and (not inside-chat?) (not locked?))
|
||||||
[quo/action-drawer
|
[quo/action-drawer
|
||||||
[[(when-not hide-view-members? (action-view-members-and-details community-id chat-id))
|
[[(when-not hide-view-members? (action-view-members-and-details community-id chat-id))
|
||||||
(action-mark-as-read)
|
(action-mark-as-read chat-id)
|
||||||
(action-toggle-muted chat-id muted muted-till chat-type)
|
(action-toggle-muted chat-id muted muted-till chat-type)
|
||||||
(action-notification-settings)
|
(action-notification-settings)
|
||||||
(action-pinned-messages chat-id)
|
(action-pinned-messages chat-id)
|
||||||
@@ -143,7 +142,7 @@
|
|||||||
[[(action-view-members-and-details community-id chat-id)
|
[[(action-view-members-and-details community-id chat-id)
|
||||||
(when token-gated?
|
(when token-gated?
|
||||||
(action-token-requirements))
|
(action-token-requirements))
|
||||||
(action-mark-as-read)
|
(action-mark-as-read chat-id)
|
||||||
(action-toggle-muted chat-id muted muted-till chat-type)
|
(action-toggle-muted chat-id muted muted-till chat-type)
|
||||||
(action-notification-settings)
|
(action-notification-settings)
|
||||||
(when config/fetch-messages-enabled?
|
(when config/fetch-messages-enabled?
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[status-im.navigation.events :as navigation]
|
[status-im.navigation.events :as navigation]
|
||||||
[status-im.navigation.transitions :as transitions]
|
[status-im.navigation.transitions :as transitions]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
|
[utils.collection :as collection-utils]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn handle-community
|
(defn handle-community
|
||||||
@@ -372,15 +373,14 @@
|
|||||||
(when (and community joined (not fetching-revealed-accounts))
|
(when (and community joined (not fetching-revealed-accounts))
|
||||||
{:db (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
|
{:db (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
|
||||||
:json-rpc/call
|
:json-rpc/call
|
||||||
[{:method "wakuext_getRevealedAccounts"
|
[{:method "wakuext_latestRequestToJoinForCommunity"
|
||||||
:params [community-id (get-in db [:profile/profile :public-key])]
|
:params [community-id]
|
||||||
:js-response true
|
:on-success [:communities/get-revealed-accounts-success community-id on-success]
|
||||||
:on-success [:communities/get-revealed-accounts-success community-id on-success]
|
:on-error (fn [err]
|
||||||
:on-error (fn [err]
|
(log/error {:message "failed to fetch revealed accounts"
|
||||||
(log/error {:message "failed to fetch revealed accounts"
|
:community-id community-id
|
||||||
:community-id community-id
|
:err err})
|
||||||
:err err})
|
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
|
||||||
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/get-revealed-accounts get-revealed-accounts)
|
(rf/reg-event-fx :communities/get-revealed-accounts get-revealed-accounts)
|
||||||
|
|
||||||
@@ -399,22 +399,18 @@
|
|||||||
[:json-rpc/call :schema.common/rpc-call]]]])
|
[:json-rpc/call :schema.common/rpc-call]]]])
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/get-revealed-accounts-success
|
(rf/reg-event-fx :communities/get-revealed-accounts-success
|
||||||
(fn [{:keys [db]} [community-id on-success revealed-accounts-js]]
|
(fn [{:keys [db]} [community-id on-success request-to-join]]
|
||||||
(when-let [community (get-in db [:communities community-id])]
|
(when-let [community (get-in db [:communities community-id])]
|
||||||
(let [revealed-accounts
|
(let [revealed-accounts (collection-utils/index-by :address (:revealedAccounts request-to-join))
|
||||||
(reduce
|
share-future-addresses? (:shareFutureAddresses request-to-join)
|
||||||
(fn [acc {:keys [address] :as revealed-account}]
|
|
||||||
(assoc acc address revealed-account))
|
|
||||||
{}
|
|
||||||
(data-store.communities/<-revealed-accounts-rpc revealed-accounts-js))
|
|
||||||
|
|
||||||
community-with-revealed-accounts
|
community-with-revealed-accounts
|
||||||
(-> community
|
(-> community
|
||||||
(assoc :revealed-accounts revealed-accounts)
|
(assoc :revealed-accounts revealed-accounts)
|
||||||
|
(assoc :share-future-addresses? share-future-addresses?)
|
||||||
(dissoc :fetching-revealed-accounts))]
|
(dissoc :fetching-revealed-accounts))]
|
||||||
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)
|
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)
|
||||||
:fx [(when (vector? on-success)
|
:fx [(when (vector? on-success)
|
||||||
[:dispatch (conj on-success revealed-accounts)])]}))))
|
[:dispatch (conj on-success revealed-accounts share-future-addresses?)])]}))))
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/get-revealed-accounts-failed
|
(rf/reg-event-fx :communities/get-revealed-accounts-failed
|
||||||
(fn [{:keys [db]} [community-id]]
|
(fn [{:keys [db]} [community-id]]
|
||||||
|
|||||||
@@ -146,8 +146,8 @@
|
|||||||
effects (events/get-revealed-accounts {:db db} [community-id])]
|
effects (events/get-revealed-accounts {:db db} [community-id])]
|
||||||
(is (match? (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
|
(is (match? (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
|
||||||
(:db effects)))
|
(:db effects)))
|
||||||
(is (match? {:method "wakuext_getRevealedAccounts"
|
(is (match? {:method "wakuext_latestRequestToJoinForCommunity"
|
||||||
:params [community-id "profile-public-key"]}
|
:params [community-id]}
|
||||||
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
|
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
|
||||||
|
|
||||||
(deftest handle-community-test
|
(deftest handle-community-test
|
||||||
|
|||||||
@@ -117,13 +117,14 @@
|
|||||||
{:community community-name})}]]]})))
|
{:community community-name})}]]]})))
|
||||||
|
|
||||||
(defn request-to-join-with-signatures
|
(defn request-to-join-with-signatures
|
||||||
[_ [community-id addresses-to-reveal signatures]]
|
[_ [community-id addresses-to-reveal signatures share-future-addresses?]]
|
||||||
{:fx [[:json-rpc/call
|
{:fx [[:json-rpc/call
|
||||||
[{:method "wakuext_requestToJoinCommunity"
|
[{:method "wakuext_requestToJoinCommunity"
|
||||||
:params [{:communityId community-id
|
:params [{:communityId community-id
|
||||||
:signatures signatures
|
:signatures signatures
|
||||||
:addressesToReveal addresses-to-reveal
|
:addressesToReveal addresses-to-reveal
|
||||||
:airdropAddress (first addresses-to-reveal)}]
|
:shareFutureAddresses share-future-addresses?
|
||||||
|
:airdropAddress (first addresses-to-reveal)}]
|
||||||
:js-response true
|
:js-response true
|
||||||
:on-success [:communities/requested-to-join]
|
:on-success [:communities/requested-to-join]
|
||||||
:on-error [:communities/requested-to-join-error community-id]}]]]})
|
:on-error [:communities/requested-to-join-error community-id]}]]]})
|
||||||
@@ -153,16 +154,18 @@
|
|||||||
(defn request-to-join-with-addresses
|
(defn request-to-join-with-addresses
|
||||||
[{:keys [db]}
|
[{:keys [db]}
|
||||||
[{:keys [community-id password]}]]
|
[{:keys [community-id password]}]]
|
||||||
(let [pub-key (get-in db [:profile/profile :public-key])
|
(let [pub-key (get-in db [:profile/profile :public-key])
|
||||||
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
|
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
|
||||||
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
|
share-future-addresses? (get-in db [:communities/selected-share-all-addresses community-id])
|
||||||
|
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
|
||||||
{:fx [[:effects.community/request-to-join
|
{:fx [[:effects.community/request-to-join
|
||||||
{:community-id community-id
|
{:community-id community-id
|
||||||
:password password
|
:password password
|
||||||
:pub-key pub-key
|
:pub-key pub-key
|
||||||
:addresses-to-reveal addresses-to-reveal
|
:addresses-to-reveal addresses-to-reveal
|
||||||
:airdrop-address airdrop-address
|
:airdrop-address airdrop-address
|
||||||
:on-success [:communities/requested-to-join]
|
:share-future-addresses? share-future-addresses?
|
||||||
:on-error [:communities/requested-to-join-error community-id]}]]}))
|
:on-success [:communities/requested-to-join]
|
||||||
|
:on-error [:communities/requested-to-join-error community-id]}]]}))
|
||||||
|
|
||||||
(rf/reg-event-fx :communities/request-to-join-with-addresses request-to-join-with-addresses)
|
(rf/reg-event-fx :communities/request-to-join-with-addresses request-to-join-with-addresses)
|
||||||
|
|||||||
@@ -37,19 +37,22 @@
|
|||||||
(sut/sign-data cofx [community-id password sign-params])))))
|
(sut/sign-data cofx [community-id password sign-params])))))
|
||||||
|
|
||||||
(deftest request-to-join-with-signatures-test
|
(deftest request-to-join-with-signatures-test
|
||||||
(let [cofx {:db {}}
|
(let [cofx {:db {}}
|
||||||
addresses-to-reveal [account-pub-key "0x2"]
|
addresses-to-reveal [account-pub-key "0x2"]
|
||||||
signatures ["11111" "222222"]
|
share-future-addresses? true
|
||||||
expected {:fx [[:json-rpc/call
|
signatures ["11111" "222222"]
|
||||||
[{:method "wakuext_requestToJoinCommunity"
|
expected {:fx [[:json-rpc/call
|
||||||
:params [{:communityId community-id
|
[{:method "wakuext_requestToJoinCommunity"
|
||||||
:signatures signatures
|
:params [{:communityId community-id
|
||||||
:addressesToReveal addresses-to-reveal
|
:signatures signatures
|
||||||
:airdropAddress "0x1"}]
|
:addressesToReveal addresses-to-reveal
|
||||||
:js-response true
|
:shareFutureAddresses share-future-addresses?
|
||||||
:on-success [:communities/requested-to-join]
|
:airdropAddress "0x1"}]
|
||||||
:on-error [:communities/requested-to-join-error
|
:js-response true
|
||||||
community-id]}]]]}]
|
:on-success [:communities/requested-to-join]
|
||||||
|
:on-error [:communities/requested-to-join-error
|
||||||
|
community-id]}]]]}]
|
||||||
(is (match? expected
|
(is (match? expected
|
||||||
(sut/request-to-join-with-signatures cofx
|
(sut/request-to-join-with-signatures cofx
|
||||||
[community-id addresses-to-reveal signatures])))))
|
[community-id addresses-to-reveal signatures
|
||||||
|
share-future-addresses?])))))
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
(ns status-im.contexts.networks.events
|
||||||
|
(:require
|
||||||
|
["@react-native-community/netinfo" :default net-info]
|
||||||
|
[native-module.core :as native-module]
|
||||||
|
[status-im.feature-flags :as ff]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(rf/reg-fx
|
||||||
|
:effects.network/listen-to-network-info
|
||||||
|
(fn []
|
||||||
|
(when net-info
|
||||||
|
(.addEventListener ^js net-info
|
||||||
|
#(rf/dispatch [:network/on-state-change
|
||||||
|
(js->clj % :keywordize-keys true)])))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:network/on-state-change
|
||||||
|
(fn [{:keys [db]} [{:keys [isConnected type details]}]]
|
||||||
|
(let [old-network-status (:network/status db)
|
||||||
|
old-network-type (:network/type db)
|
||||||
|
connectivity-status (if isConnected :online :offline)
|
||||||
|
status-changed? (not= connectivity-status old-network-status)
|
||||||
|
type-changed? (not= type old-network-type)
|
||||||
|
is-connection-expensive? (:is-connection-expensive details)]
|
||||||
|
(log/debug "[net-info]"
|
||||||
|
"old-network-status" old-network-status
|
||||||
|
"old-network-type" old-network-type
|
||||||
|
"connectivity-status" connectivity-status
|
||||||
|
"type" type
|
||||||
|
"details" details)
|
||||||
|
{:fx [(when status-changed?
|
||||||
|
[:dispatch [:network/on-network-status-change isConnected]])
|
||||||
|
(when type-changed?
|
||||||
|
[:dispatch [:network/on-network-type-change type is-connection-expensive?]])]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:network/on-network-type-change
|
||||||
|
(fn [{:keys [db]} [network-type expensive?]]
|
||||||
|
{:db (assoc db :network/type network-type)
|
||||||
|
:fx [[:effects.network/notify-status-go network-type expensive?]
|
||||||
|
[:dispatch [:mobile-network/on-network-status-change]]]}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:network/on-network-status-change
|
||||||
|
(fn [{:keys [db]} [is-connected?]]
|
||||||
|
(let [network-status (if is-connected? :online :offline)]
|
||||||
|
{:db (assoc db :network/status network-status)
|
||||||
|
:fx [(when (ff/enabled? ::ff/wallet.wallet-connect)
|
||||||
|
[:dispatch [:wallet-connect/reload-on-network-change is-connected?]])]})))
|
||||||
|
|
||||||
|
(rf/reg-fx
|
||||||
|
:effects.network/notify-status-go
|
||||||
|
(fn [network-type expensive?]
|
||||||
|
(native-module/connection-change network-type expensive?)))
|
||||||
@@ -5,13 +5,8 @@
|
|||||||
|
|
||||||
(def background-container
|
(def background-container
|
||||||
{:background-color colors/neutral-100
|
{:background-color colors/neutral-100
|
||||||
:flex-direction :row
|
:flex 1
|
||||||
:position :absolute
|
:overflow :hidden})
|
||||||
:overflow :hidden
|
|
||||||
:top 0
|
|
||||||
:bottom 0
|
|
||||||
:left 0
|
|
||||||
:right 0})
|
|
||||||
|
|
||||||
(def background-blur-overlay
|
(def background-blur-overlay
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
|
|||||||
@@ -25,13 +25,12 @@
|
|||||||
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
|
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
|
||||||
|
|
||||||
(defn background-image
|
(defn background-image
|
||||||
[content-width]
|
[image-view-width]
|
||||||
[rn/image
|
[rn/image
|
||||||
{:resize-mode :stretch
|
{:resize-mode :stretch
|
||||||
:resize-method :scale
|
:style {:flex 1
|
||||||
:style {:top 138
|
:width image-view-width}
|
||||||
:width content-width}
|
:source (resources/get-image :onboarding-illustration)}])
|
||||||
:source (resources/get-image :onboarding-illustration)}])
|
|
||||||
|
|
||||||
(defonce progress (atom nil))
|
(defonce progress (atom nil))
|
||||||
(defonce paused? (atom nil))
|
(defonce paused? (atom nil))
|
||||||
|
|||||||
@@ -5,12 +5,9 @@
|
|||||||
|
|
||||||
(defn header-container
|
(defn header-container
|
||||||
[status-bar-height content-width index header-background]
|
[status-bar-height content-width index header-background]
|
||||||
{:position :absolute
|
{:margin-left (* content-width index)
|
||||||
:top 0
|
|
||||||
:left (* content-width index)
|
|
||||||
:padding-top (+ 30 status-bar-height)
|
:padding-top (+ 30 status-bar-height)
|
||||||
:width content-width
|
:width content-width
|
||||||
:height (+ 96 status-bar-height)
|
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:background-color (when header-background colors/onboarding-header-black)})
|
:background-color (when header-background colors/onboarding-header-black)})
|
||||||
|
|
||||||
@@ -62,9 +59,9 @@
|
|||||||
:top (+ 12 status-bar-height)})
|
:top (+ 12 status-bar-height)})
|
||||||
|
|
||||||
(defn carousel-container
|
(defn carousel-container
|
||||||
[left animate?]
|
[left animate? width]
|
||||||
(cond->> {:position :absolute
|
(cond->> {:flex-direction :row
|
||||||
:top 0
|
:flex 1
|
||||||
:flex-direction :row
|
:width width
|
||||||
:left left}
|
:margin-left left}
|
||||||
animate? (reanimated/apply-animations-to-style {:left left})))
|
animate? (reanimated/apply-animations-to-style {:margin-left left})))
|
||||||
|
|||||||
@@ -18,19 +18,18 @@
|
|||||||
:size :heading-2}
|
:size :heading-2}
|
||||||
(get-in header-text [index :text])]
|
(get-in header-text [index :text])]
|
||||||
[quo/text
|
[quo/text
|
||||||
{:style style/carousel-sub-text
|
{:style style/carousel-sub-text}
|
||||||
:size :paragraph-1}
|
|
||||||
(get-in header-text [index :sub-text])]])
|
(get-in header-text [index :sub-text])]])
|
||||||
|
|
||||||
(defn content-view
|
(defn content-view
|
||||||
[{:keys [window-width status-bar-height index header-text header-background]} content]
|
[{:keys [window-width status-bar-height index header-text header-background]} content]
|
||||||
(let [content-width (* 4 window-width)]
|
(let [content-width (* 4 window-width)]
|
||||||
[:<>
|
[rn/view {:style {:flex 1}}
|
||||||
(when content content)
|
|
||||||
[rn/view {:style (style/header-container status-bar-height content-width index header-background)}
|
[rn/view {:style (style/header-container status-bar-height content-width index header-background)}
|
||||||
(for [index (range 4)]
|
(for [index (range 4)]
|
||||||
^{:key index}
|
^{:key index}
|
||||||
[header-text-view index window-width header-text])]]))
|
[header-text-view index window-width header-text])]
|
||||||
|
(when content content)]))
|
||||||
|
|
||||||
(defn progress-bar
|
(defn progress-bar
|
||||||
[{:keys [static? progress-bar-width]}]
|
[{:keys [static? progress-bar-width]}]
|
||||||
@@ -64,10 +63,10 @@
|
|||||||
:swipeable (animation/composed-gestures progress paused? is-dragging? drag-amount)
|
:swipeable (animation/composed-gestures progress paused? is-dragging? drag-amount)
|
||||||
:tappable (animation/tap-gesture progress paused?)
|
:tappable (animation/tap-gesture progress paused?)
|
||||||
nil)]
|
nil)]
|
||||||
[:<>
|
[rn/view {:style {:flex 1}}
|
||||||
[gesture/gesture-detector {:gesture identified-gesture}
|
[gesture/gesture-detector {:gesture identified-gesture}
|
||||||
[container-view {:style (style/carousel-container carousel-left animate?)}
|
[container-view {:style (style/carousel-container carousel-left animate? (* 4 window-width))}
|
||||||
(for [index (range 2)]
|
(for [index (range 1)]
|
||||||
^{:key index}
|
^{:key index}
|
||||||
[content-view
|
[content-view
|
||||||
{:window-width window-width
|
{:window-width window-width
|
||||||
|
|||||||
@@ -17,3 +17,17 @@
|
|||||||
{:events [:onboarding/overlay-dismiss]}
|
{:events [:onboarding/overlay-dismiss]}
|
||||||
[_]
|
[_]
|
||||||
{:onboarding/overlay-dismiss-fx nil})
|
{:onboarding/overlay-dismiss-fx nil})
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:onboarding/overlay-show-fx
|
||||||
|
(fn []
|
||||||
|
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
|
||||||
|
(blur-show-fn))
|
||||||
|
(when-let [push-animation-fn @profiles/push-animation-fn-atom]
|
||||||
|
(push-animation-fn))))
|
||||||
|
|
||||||
|
(rf/defn overlay-show
|
||||||
|
{:events [:onboarding/overlay-show]}
|
||||||
|
[_]
|
||||||
|
{:onboarding/overlay-show-fx nil})
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[status-im.common.check-before-syncing.view :as check-before-syncing]
|
[status-im.common.check-before-syncing.view :as check-before-syncing]
|
||||||
|
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
|
||||||
[status-im.common.not-implemented :as not-implemented]
|
[status-im.common.not-implemented :as not-implemented]
|
||||||
[status-im.common.resources :as resources]
|
[status-im.common.resources :as resources]
|
||||||
[status-im.config :as config]
|
[status-im.config :as config]
|
||||||
@@ -126,6 +127,7 @@
|
|||||||
|
|
||||||
(defn- internal-view
|
(defn- internal-view
|
||||||
[sign-in-type]
|
[sign-in-type]
|
||||||
|
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
|
||||||
(let [{:keys [top]} (safe-area/get-insets)]
|
(let [{:keys [top]} (safe-area/get-insets)]
|
||||||
[rn/view {:style style/content-container}
|
[rn/view {:style style/content-container}
|
||||||
[quo/page-nav
|
[quo/page-nav
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
|
|
||||||
(def title-container
|
(def title-container
|
||||||
{:margin-horizontal 20
|
{:margin-horizontal 20
|
||||||
:padding-vertical 12})
|
:padding-bottom 20
|
||||||
|
:padding-top 12})
|
||||||
|
|
||||||
(defn page-container
|
(defn page-container
|
||||||
[insets]
|
[insets]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:justify-content :space-between
|
:padding-top (+ (:top insets) 56)})
|
||||||
:padding-top (+ (:top insets) 56)})
|
|
||||||
|
|
||||||
(defn page-illustration
|
(defn page-illustration
|
||||||
[width]
|
[width]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:padding-top 12
|
:margin-top 12
|
||||||
:padding-bottom 10
|
:margin-bottom 10
|
||||||
:width width})
|
:width width})
|
||||||
|
|
||||||
(defn buttons
|
(defn buttons
|
||||||
[insets]
|
[insets]
|
||||||
|
|||||||
@@ -73,7 +73,9 @@
|
|||||||
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
||||||
:screen/onboarding.new-to-status)]]
|
:screen/onboarding.new-to-status)]]
|
||||||
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
|
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
|
||||||
:dispatch [:init-root :screen/onboarding.enable-notifications]}]
|
:dispatch [:navigate-to-within-stack
|
||||||
|
[:screen/onboarding.enable-notifications
|
||||||
|
:screen/onboarding.generating-keys]]}]
|
||||||
:db (-> db
|
:db (-> db
|
||||||
(dissoc :profile/login)
|
(dissoc :profile/login)
|
||||||
(dissoc :auth-method)
|
(dissoc :auth-method)
|
||||||
@@ -123,25 +125,31 @@
|
|||||||
mnemonic key-uid]))
|
mnemonic key-uid]))
|
||||||
on-error]})
|
on-error]})
|
||||||
|
|
||||||
|
;; TODO: clear syncing data if key-uid does not match
|
||||||
(rf/defn seed-phrase-validated
|
(rf/defn seed-phrase-validated
|
||||||
{:events [:onboarding/seed-phrase-validated]}
|
{:events [:onboarding/seed-phrase-validated]}
|
||||||
[{:keys [db]} seed-phrase key-uid]
|
[{:keys [db]} seed-phrase key-uid]
|
||||||
(if (contains? (:profile/profiles-overview db) key-uid)
|
(let [next-screen (if (and (seq (:syncing/key-uid db))
|
||||||
{:effects.utils/show-confirmation
|
(= (:syncing/key-uid db) key-uid))
|
||||||
{:title (i18n/label :t/multiaccount-exists-title)
|
:screen/onboarding.create-profile-password
|
||||||
:content (i18n/label :t/multiaccount-exists-content)
|
:screen/onboarding.create-profile)]
|
||||||
:confirm-button-text (i18n/label :t/unlock)
|
|
||||||
:on-accept (fn []
|
(if (contains? (:profile/profiles-overview db) key-uid)
|
||||||
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
|
{:effects.utils/show-confirmation
|
||||||
(re-frame/dispatch
|
{:title (i18n/label :t/multiaccount-exists-title)
|
||||||
[:profile/profile-selected key-uid]))
|
:content (i18n/label :t/multiaccount-exists-content)
|
||||||
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
|
:confirm-button-text (i18n/label :t/unlock)
|
||||||
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
|
:on-accept (fn []
|
||||||
:dispatch [:navigate-to-within-stack
|
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
|
||||||
[:screen/onboarding.create-profile
|
(re-frame/dispatch
|
||||||
(get db
|
[:profile/profile-selected key-uid]))
|
||||||
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
|
||||||
:screen/onboarding.new-to-status)]]}))
|
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
|
||||||
|
:dispatch [:navigate-to-within-stack
|
||||||
|
[next-screen
|
||||||
|
(get db
|
||||||
|
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
||||||
|
:screen/onboarding.new-to-status)]]})))
|
||||||
|
|
||||||
(rf/defn navigate-to-create-profile
|
(rf/defn navigate-to-create-profile
|
||||||
{:events [:onboarding/navigate-to-create-profile]}
|
{:events [:onboarding/navigate-to-create-profile]}
|
||||||
@@ -187,14 +195,3 @@
|
|||||||
{:key-uid key-uid
|
{:key-uid key-uid
|
||||||
:error %})}))))
|
:error %})}))))
|
||||||
|
|
||||||
(rf/defn navigate-to-identifiers
|
|
||||||
{:events [:onboarding/navigate-to-identifiers]}
|
|
||||||
[{:keys [db]}]
|
|
||||||
(if (:onboarding/generated-keys? db)
|
|
||||||
{:dispatch [:navigate-to-within-stack
|
|
||||||
[:screen/onboarding.identifiers
|
|
||||||
(get db
|
|
||||||
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
|
||||||
:screen/onboarding.new-to-status)]]}
|
|
||||||
{:dispatch-later [{:ms constants/onboarding-generating-keys-navigation-retry-ms
|
|
||||||
:dispatch [:onboarding/navigate-to-identifiers]}]}))
|
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
(defn page-container
|
(defn page-container
|
||||||
[insets]
|
[insets]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:justify-content :space-between
|
:padding-top (:top insets)})
|
||||||
:padding-top (:top insets)})
|
|
||||||
|
|
||||||
(defn page-illustration
|
(defn page-illustration
|
||||||
[width]
|
[width]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:width width})
|
:width width})
|
||||||
|
|
||||||
|
(def title-style
|
||||||
|
{:position :absolute
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:top 0})
|
||||||
|
|||||||
@@ -17,19 +17,22 @@
|
|||||||
(defn generate-keys-title
|
(defn generate-keys-title
|
||||||
[]
|
[]
|
||||||
[quo/text-combinations
|
[quo/text-combinations
|
||||||
{:container-style {:margin-horizontal 20}
|
{:container-style {:margin-horizontal 20
|
||||||
|
:margin-vertical 12}
|
||||||
:title (i18n/label :t/generating-keys)}])
|
:title (i18n/label :t/generating-keys)}])
|
||||||
|
|
||||||
(defn saving-keys-title
|
(defn saving-keys-title
|
||||||
[]
|
[]
|
||||||
[quo/text-combinations
|
[quo/text-combinations
|
||||||
{:container-style {:margin-horizontal 20}
|
{:container-style {:margin-horizontal 20
|
||||||
|
:margin-vertical 12}
|
||||||
:title (i18n/label :t/saving-keys-to-device)}])
|
:title (i18n/label :t/saving-keys-to-device)}])
|
||||||
|
|
||||||
(defn keys-saved-title
|
(defn keys-saved-title
|
||||||
[]
|
[]
|
||||||
[quo/text-combinations
|
[quo/text-combinations
|
||||||
{:container-style {:margin-horizontal 20}
|
{:container-style {:margin-horizontal 20
|
||||||
|
:margin-vertical 12}
|
||||||
:title (i18n/label :t/keys-saved)}])
|
:title (i18n/label :t/keys-saved)}])
|
||||||
|
|
||||||
(defn sequence-animation
|
(defn sequence-animation
|
||||||
@@ -61,46 +64,42 @@
|
|||||||
reanimated/easings))))))
|
reanimated/easings))))))
|
||||||
|
|
||||||
(defn title
|
(defn title
|
||||||
[insets]
|
[]
|
||||||
(let [top-insets (+ (if rn/small-screen? 62 112) (:insets insets))
|
(let [generate-keys-opacity (reanimated/use-shared-value 1)
|
||||||
generate-keys-opacity (reanimated/use-shared-value 1)
|
|
||||||
saving-keys-opacity (reanimated/use-shared-value 0)
|
saving-keys-opacity (reanimated/use-shared-value 0)
|
||||||
keys-saved-opacity (reanimated/use-shared-value 0)]
|
keys-saved-opacity (reanimated/use-shared-value 0)]
|
||||||
(sequence-animation generate-keys-opacity saving-keys-opacity keys-saved-opacity)
|
(sequence-animation generate-keys-opacity saving-keys-opacity keys-saved-opacity)
|
||||||
[rn/view
|
[rn/view
|
||||||
{:position :absolute
|
{:style {:margin-top 56
|
||||||
:top top-insets}
|
:height 56}}
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (reanimated/apply-animations-to-style
|
{:style (reanimated/apply-animations-to-style
|
||||||
{:opacity generate-keys-opacity}
|
{:opacity generate-keys-opacity}
|
||||||
{:position :absolute})}
|
style/title-style)}
|
||||||
[generate-keys-title]]
|
[generate-keys-title]]
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (reanimated/apply-animations-to-style
|
{:style (reanimated/apply-animations-to-style
|
||||||
{:opacity saving-keys-opacity}
|
{:opacity saving-keys-opacity}
|
||||||
{:position :absolute})}
|
style/title-style)}
|
||||||
[saving-keys-title]]
|
[saving-keys-title]]
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (reanimated/apply-animations-to-style
|
{:style (reanimated/apply-animations-to-style
|
||||||
{:opacity keys-saved-opacity}
|
{:opacity keys-saved-opacity}
|
||||||
{:position :absolute})}
|
style/title-style)}
|
||||||
[keys-saved-title]]]))
|
[keys-saved-title]]]))
|
||||||
|
|
||||||
(defn content
|
(defn content
|
||||||
[]
|
[]
|
||||||
(let [width (:width (rn/get-window))]
|
(let [width (:width (rn/get-window))]
|
||||||
[rn/view
|
[rn/image
|
||||||
{:top 156
|
{:resize-mode :contain
|
||||||
:position :absolute}
|
:style (style/page-illustration width)
|
||||||
[rn/image
|
:source (resources/get-image :generate-keys1)}]))
|
||||||
{:resize-mode :contain
|
|
||||||
:style (style/page-illustration width)
|
|
||||||
:source (resources/get-image :generate-keys1)}]]))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
(let [insets (safe-area/get-insets)]
|
(let [insets (safe-area/get-insets)]
|
||||||
[rn/view {:style (style/page-container insets)}
|
[rn/view {:style (style/page-container insets)}
|
||||||
[:<>
|
[:<>
|
||||||
[title insets]
|
[title]
|
||||||
[content]]]))
|
[content]]]))
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
:justify-content :flex-end})
|
:justify-content :flex-end})
|
||||||
|
|
||||||
(def text-container
|
(def text-container
|
||||||
{:flex 1
|
{:text-align :center
|
||||||
:text-align :center
|
:margin-top 4
|
||||||
:margin-top 16
|
|
||||||
:flex-wrap :wrap})
|
:flex-wrap :wrap})
|
||||||
|
|
||||||
(def plain-text
|
(def plain-text
|
||||||
@@ -19,9 +18,8 @@
|
|||||||
{:flex 1
|
{:flex 1
|
||||||
:color colors/white})
|
:color colors/white})
|
||||||
|
|
||||||
(def bottom-actions-container
|
(defn bottom-actions-container
|
||||||
{:position :absolute
|
[bottom-insets]
|
||||||
:background-color colors/onboarding-header-black
|
{:background-color colors/onboarding-header-black
|
||||||
:left 0
|
:flex-shrink 1
|
||||||
:right 0
|
:padding-bottom (+ 20 bottom-insets)})
|
||||||
:padding-bottom 40})
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[react-native.safe-area :as safe-area]
|
||||||
[status-im.contexts.onboarding.common.background.view :as background]
|
[status-im.contexts.onboarding.common.background.view :as background]
|
||||||
[status-im.contexts.onboarding.common.overlay.view :as overlay]
|
[status-im.contexts.onboarding.common.overlay.view :as overlay]
|
||||||
[status-im.contexts.onboarding.intro.style :as style]
|
[status-im.contexts.onboarding.intro.style :as style]
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
[rn/view {:style style/page-container}
|
[rn/view {:style style/page-container}
|
||||||
[background/view false]
|
[background/view false]
|
||||||
[quo/bottom-actions
|
[quo/bottom-actions
|
||||||
{:container-style style/bottom-actions-container
|
{:container-style (style/bottom-actions-container (safe-area/get-bottom))
|
||||||
:actions :two-vertical-actions
|
:actions :two-vertical-actions
|
||||||
:description :bottom
|
:description :bottom
|
||||||
:description-text [quo/text
|
:description-text [quo/text
|
||||||
|
|||||||
@@ -2,6 +2,13 @@
|
|||||||
(:require
|
(:require
|
||||||
[quo.foundations.colors :as colors]))
|
[quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def absolute-fill
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0})
|
||||||
|
|
||||||
(defn page-container
|
(defn page-container
|
||||||
[in-onboarding?]
|
[in-onboarding?]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
|
|||||||
@@ -26,33 +26,62 @@
|
|||||||
:title-accessibility-label :progress-screen-title
|
:title-accessibility-label :progress-screen-title
|
||||||
:description-accessibility-label :progress-screen-sub-title}])
|
:description-accessibility-label :progress-screen-sub-title}])
|
||||||
|
|
||||||
|
(defn navigate-to-enter-seed-phrase
|
||||||
|
[view-id]
|
||||||
|
(if (= view-id :screen/onboarding.syncing-progress-intro)
|
||||||
|
(do
|
||||||
|
(rf/dispatch [:navigate-back-to :screen/onboarding.sync-or-recover-profile])
|
||||||
|
(debounce/debounce-and-dispatch
|
||||||
|
[:onboarding/navigate-to-sign-in-by-seed-phrase :screen/onboarding.sync-or-recover-profile]
|
||||||
|
300))
|
||||||
|
(do
|
||||||
|
(rf/dispatch [:navigate-back])
|
||||||
|
(debounce/debounce-and-dispatch [:onboarding/overlay-show] 100)
|
||||||
|
(debounce/debounce-and-dispatch [:open-modal :screen/onboarding.new-to-status] 200)
|
||||||
|
(debounce/debounce-and-dispatch
|
||||||
|
[:onboarding/navigate-to-sign-in-by-seed-phrase :screen/onboarding.new-to-status]
|
||||||
|
300))))
|
||||||
|
|
||||||
(defn try-again-button
|
(defn try-again-button
|
||||||
[profile-color in-onboarding? logged-in?]
|
[profile-color in-onboarding? logged-in? view-id]
|
||||||
[quo/button
|
[rn/view
|
||||||
{:on-press (fn []
|
(when-not logged-in?
|
||||||
(rf/dispatch [:syncing/clear-states])
|
[quo/button
|
||||||
(cond
|
{:on-press #(navigate-to-enter-seed-phrase view-id)
|
||||||
logged-in? (rf/dispatch [:navigate-back])
|
:accessibility-label :try-seed-phrase-button
|
||||||
in-onboarding? (rf/dispatch [:navigate-back-to
|
:customization-color profile-color
|
||||||
:screen/onboarding.sign-in-intro])
|
:container-style style/try-again-button}
|
||||||
:else (do
|
(i18n/label :t/enter-seed-phrase)])
|
||||||
(rf/dispatch [:navigate-back])
|
|
||||||
(debounce/throttle-and-dispatch
|
|
||||||
[:open-modal
|
[quo/button
|
||||||
:screen/onboarding.sign-in]
|
{:on-press (fn []
|
||||||
1000))))
|
(rf/dispatch [:syncing/clear-states])
|
||||||
:accessibility-label :try-again-later-button
|
(cond
|
||||||
:customization-color profile-color
|
logged-in? (rf/dispatch [:navigate-back])
|
||||||
:container-style style/try-again-button}
|
in-onboarding? (rf/dispatch [:navigate-back-to
|
||||||
(i18n/label :t/try-again)])
|
:screen/onboarding.sign-in-intro])
|
||||||
|
:else (do
|
||||||
|
(rf/dispatch [:navigate-back])
|
||||||
|
(debounce/throttle-and-dispatch
|
||||||
|
[:open-modal
|
||||||
|
:screen/onboarding.sign-in]
|
||||||
|
1000))))
|
||||||
|
:accessibility-label :try-again-later-button
|
||||||
|
:customization-color profile-color
|
||||||
|
:container-style style/try-again-button}
|
||||||
|
(i18n/label :t/try-again)]])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[in-onboarding?]
|
[in-onboarding?]
|
||||||
(let [pairing-status (rf/sub [:pairing/pairing-status])
|
(let [pairing-status (rf/sub [:pairing/pairing-status])
|
||||||
profile-color (:color (rf/sub [:onboarding/profile]))
|
profile-color (:color (rf/sub [:onboarding/profile]))
|
||||||
logged-in? (rf/sub [:multiaccount/logged-in?])]
|
logged-in? (rf/sub [:multiaccount/logged-in?])
|
||||||
|
view-id (rf/sub [:view-id])]
|
||||||
[rn/view {:style (style/page-container in-onboarding?)}
|
[rn/view {:style (style/page-container in-onboarding?)}
|
||||||
(when-not in-onboarding? [background/view true])
|
(when-not in-onboarding?
|
||||||
|
[rn/view {:style style/absolute-fill}
|
||||||
|
[background/view true]])
|
||||||
[quo/page-nav {:type :no-title :background :blur}]
|
[quo/page-nav {:type :no-title :background :blur}]
|
||||||
[page-title (pairing-progress pairing-status)]
|
[page-title (pairing-progress pairing-status)]
|
||||||
(if config/show-not-implemented-features?
|
(if config/show-not-implemented-features?
|
||||||
@@ -63,7 +92,7 @@
|
|||||||
[quo/text "[Error here]"]])
|
[quo/text "[Error here]"]])
|
||||||
[rn/view {:flex 1}])
|
[rn/view {:flex 1}])
|
||||||
(when-not (pairing-progress pairing-status)
|
(when-not (pairing-progress pairing-status)
|
||||||
[try-again-button profile-color in-onboarding? logged-in?])]))
|
[try-again-button profile-color in-onboarding? logged-in? view-id])]))
|
||||||
|
|
||||||
(defn view-onboarding
|
(defn view-onboarding
|
||||||
[]
|
[]
|
||||||
|
|||||||
@@ -3,6 +3,13 @@
|
|||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
[react-native.reanimated :as reanimated]))
|
[react-native.reanimated :as reanimated]))
|
||||||
|
|
||||||
|
(def absolute-fill
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0})
|
||||||
|
|
||||||
(defn page-container
|
(defn page-container
|
||||||
[top]
|
[top]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
|
|||||||
@@ -66,7 +66,8 @@
|
|||||||
translate-x (reanimated/use-shared-value 0)
|
translate-x (reanimated/use-shared-value 0)
|
||||||
window-width (:width (rn/get-window))]
|
window-width (:width (rn/get-window))]
|
||||||
[rn/view {:style (style/page-container top)}
|
[rn/view {:style (style/page-container top)}
|
||||||
[background/view true]
|
[rn/view {:style style/absolute-fill}
|
||||||
|
[background/view true]]
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (style/content translate-x)}
|
{:style (style/content translate-x)}
|
||||||
[page-title]
|
[page-title]
|
||||||
|
|||||||
@@ -13,14 +13,17 @@
|
|||||||
:value "Default"}
|
:value "Default"}
|
||||||
{:key :active
|
{:key :active
|
||||||
:value "Active"}]}
|
:value "Active"}]}
|
||||||
{:key :action
|
{:key :dapp
|
||||||
:type :select
|
:type :select
|
||||||
:options [{:key :none
|
:options [{:value "With icon"
|
||||||
:value "None"}
|
:key {:avatar (resources/get-dapp :coingecko)
|
||||||
{:key :icon
|
:name "Coingecko"
|
||||||
:value "Icon"}]}
|
:value "coingecko.com"}}
|
||||||
{:key :blur?
|
{:value "Without icon"
|
||||||
:type :boolean}])
|
:key {:avatar nil
|
||||||
|
:name "Coingecko"
|
||||||
|
:value "coingecko.com"
|
||||||
|
:customization-color :blue}}]}])
|
||||||
|
|
||||||
(defn preview
|
(defn preview
|
||||||
[]
|
[]
|
||||||
|
|||||||
@@ -170,6 +170,7 @@
|
|||||||
[status-im.contexts.preview.quo.settings.settings-item :as settings-item]
|
[status-im.contexts.preview.quo.settings.settings-item :as settings-item]
|
||||||
[status-im.contexts.preview.quo.share.qr-code :as qr-code]
|
[status-im.contexts.preview.quo.share.qr-code :as qr-code]
|
||||||
[status-im.contexts.preview.quo.share.share-qr-code :as share-qr-code]
|
[status-im.contexts.preview.quo.share.share-qr-code :as share-qr-code]
|
||||||
|
[status-im.contexts.preview.quo.slideshow.slider-bar :as slider-bar]
|
||||||
[status-im.contexts.preview.quo.style :as style]
|
[status-im.contexts.preview.quo.style :as style]
|
||||||
[status-im.contexts.preview.quo.switcher.group-messaging-card :as
|
[status-im.contexts.preview.quo.switcher.group-messaging-card :as
|
||||||
group-messaging-card]
|
group-messaging-card]
|
||||||
@@ -211,6 +212,7 @@
|
|||||||
[status-im.contexts.preview.quo.wallet.progress-bar :as progress-bar]
|
[status-im.contexts.preview.quo.wallet.progress-bar :as progress-bar]
|
||||||
[status-im.contexts.preview.quo.wallet.required-tokens :as required-tokens]
|
[status-im.contexts.preview.quo.wallet.required-tokens :as required-tokens]
|
||||||
[status-im.contexts.preview.quo.wallet.summary-info :as summary-info]
|
[status-im.contexts.preview.quo.wallet.summary-info :as summary-info]
|
||||||
|
[status-im.contexts.preview.quo.wallet.swap-input :as swap-input]
|
||||||
[status-im.contexts.preview.quo.wallet.token-input :as token-input]
|
[status-im.contexts.preview.quo.wallet.token-input :as token-input]
|
||||||
[status-im.contexts.preview.quo.wallet.transaction-progress :as transaction-progress]
|
[status-im.contexts.preview.quo.wallet.transaction-progress :as transaction-progress]
|
||||||
[status-im.contexts.preview.quo.wallet.transaction-summary :as
|
[status-im.contexts.preview.quo.wallet.transaction-summary :as
|
||||||
@@ -502,6 +504,8 @@
|
|||||||
:component qr-code/view}
|
:component qr-code/view}
|
||||||
{:name :share-qr-code
|
{:name :share-qr-code
|
||||||
:component share-qr-code/view}]
|
:component share-qr-code/view}]
|
||||||
|
:slideshow [{:name :slider-bar
|
||||||
|
:component slider-bar/view}]
|
||||||
:switchers [{:name :group-messaging-card
|
:switchers [{:name :group-messaging-card
|
||||||
:component group-messaging-card/view}
|
:component group-messaging-card/view}
|
||||||
{:name :switcher-cards
|
{:name :switcher-cards
|
||||||
@@ -567,6 +571,7 @@
|
|||||||
{:name :required-tokens
|
{:name :required-tokens
|
||||||
:component required-tokens/view}
|
:component required-tokens/view}
|
||||||
{:name :summary-info :component summary-info/view}
|
{:name :summary-info :component summary-info/view}
|
||||||
|
{:name :swap-input :component swap-input/view}
|
||||||
{:name :token-input :component token-input/view}
|
{:name :token-input :component token-input/view}
|
||||||
{:name :wallet-activity :component wallet-activity/view}
|
{:name :wallet-activity :component wallet-activity/view}
|
||||||
{:name :transaction-progress :component transaction-progress/view}
|
{:name :transaction-progress :component transaction-progress/view}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
(ns status-im.contexts.preview.quo.slideshow.slider-bar
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im.contexts.preview.quo.preview :as preview]))
|
||||||
|
|
||||||
|
(def descriptor
|
||||||
|
[{:key :total-amount
|
||||||
|
:type :number}
|
||||||
|
{:label "Blur (dark only)?"
|
||||||
|
:key :blur?
|
||||||
|
:type :boolean}
|
||||||
|
(preview/customization-color-option)])
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
(let [[state set-state] (rn/use-state {:total-amount 10
|
||||||
|
:active-index 0
|
||||||
|
:blur? false
|
||||||
|
:customization-color :blue})]
|
||||||
|
[preview/preview-container
|
||||||
|
{:state state
|
||||||
|
:set-state set-state
|
||||||
|
:descriptor descriptor
|
||||||
|
:blur? (:blur? state)
|
||||||
|
:show-blur-background? true
|
||||||
|
:blur-dark-only? true}
|
||||||
|
[rn/view
|
||||||
|
{:style {:flex-direction :row
|
||||||
|
:justify-content :center
|
||||||
|
:gap 10
|
||||||
|
:padding 10}}
|
||||||
|
[quo/button
|
||||||
|
{:type :outline
|
||||||
|
:style {:disabled true}
|
||||||
|
:disabled? (zero? (:active-index state))
|
||||||
|
:icon-only? true
|
||||||
|
:on-press (fn []
|
||||||
|
(set-state (update state :active-index dec)))}
|
||||||
|
:i/chevron-left]
|
||||||
|
[quo/button
|
||||||
|
{:type :outline
|
||||||
|
:disabled? (= (:active-index state)
|
||||||
|
(dec (:total-amount state)))
|
||||||
|
:icon-only? true
|
||||||
|
:on-press (fn []
|
||||||
|
(set-state (update state :active-index inc)))}
|
||||||
|
:i/chevron-right]]
|
||||||
|
[quo/slider-bar state]]))
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
(ns status-im.contexts.preview.quo.wallet.swap-input
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[quo.foundations.resources :as resources]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im.contexts.preview.quo.preview :as preview]))
|
||||||
|
|
||||||
|
(def descriptor
|
||||||
|
[{:type :select
|
||||||
|
:key :type
|
||||||
|
:options [{:key :pay}
|
||||||
|
{:key :receive}]}
|
||||||
|
{:type :select
|
||||||
|
:key :status
|
||||||
|
:options [{:key :default}
|
||||||
|
{:key :disabled}
|
||||||
|
{:key :loading}]}
|
||||||
|
{:type :select
|
||||||
|
:key :value
|
||||||
|
:options [{:key :token}
|
||||||
|
{:key :fiat}]}
|
||||||
|
{:type :boolean
|
||||||
|
:key :error?}
|
||||||
|
{:type :boolean
|
||||||
|
:key :enable-swap?}
|
||||||
|
{:type :boolean
|
||||||
|
:key :show-approval-label?}
|
||||||
|
(preview/customization-color-option)])
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
(let [[state set-state] (rn/use-state {:type :pay
|
||||||
|
:error? false
|
||||||
|
:token "SNT"
|
||||||
|
:customization-color :blue
|
||||||
|
:show-approval-label? false
|
||||||
|
:enable-swap? true
|
||||||
|
:status :default
|
||||||
|
:currency-symbol "€"})
|
||||||
|
[value set-value] (rn/use-state "")
|
||||||
|
on-press (fn [v] (set-value (str value v)))
|
||||||
|
delete (fn [] (set-value #(subs % 0 (dec (count %)))))]
|
||||||
|
[preview/preview-container
|
||||||
|
{:state state
|
||||||
|
:set-state set-state
|
||||||
|
:descriptor descriptor}
|
||||||
|
[quo/swap-input
|
||||||
|
(assoc state
|
||||||
|
:on-swap-press #(js/alert "Swap Pressed")
|
||||||
|
:on-token-press #(js/alert "Token Pressed")
|
||||||
|
:on-max-press #(js/alert "Max Pressed")
|
||||||
|
:value value
|
||||||
|
:fiat-value (str (.toFixed (* value 0.3) 2))
|
||||||
|
:container-style {:margin-bottom 20}
|
||||||
|
:network-tag-props {:title "Max: 200 SNT"
|
||||||
|
:networks [{:source (resources/get-network :ethereum)}]}
|
||||||
|
:approval-label-props
|
||||||
|
{:status :approve
|
||||||
|
:token-value "10"
|
||||||
|
:button-props {:on-press
|
||||||
|
#(js/alert "Approve Pressed")}
|
||||||
|
:customization-color (:customization-color state)
|
||||||
|
:token-symbol "SNT"})]
|
||||||
|
[quo/numbered-keyboard
|
||||||
|
{:left-action :dot
|
||||||
|
:delete-key? true
|
||||||
|
:on-press on-press
|
||||||
|
:on-delete delete}]]))
|
||||||
@@ -29,19 +29,21 @@
|
|||||||
[]
|
[]
|
||||||
(let [log-enabled? (boolean (not-empty config/log-level))]
|
(let [log-enabled? (boolean (not-empty config/log-level))]
|
||||||
(assoc (login)
|
(assoc (login)
|
||||||
:deviceName (native-module/get-installation-name)
|
:deviceName (native-module/get-installation-name)
|
||||||
:rootDataDir (native-module/backup-disabled-data-dir)
|
:rootDataDir (native-module/backup-disabled-data-dir)
|
||||||
:rootKeystoreDir (native-module/keystore-dir)
|
:rootKeystoreDir (native-module/keystore-dir)
|
||||||
:logLevel (when log-enabled? config/log-level)
|
:logLevel (when log-enabled? config/log-level)
|
||||||
:logEnabled log-enabled?
|
:logEnabled log-enabled?
|
||||||
:logFilePath (native-module/log-file-directory)
|
:logFilePath (native-module/log-file-directory)
|
||||||
:verifyTransactionURL config/verify-transaction-url
|
:verifyTransactionURL config/verify-transaction-url
|
||||||
:verifyENSURL config/verify-ens-url
|
:verifyENSURL config/verify-ens-url
|
||||||
:verifyENSContractAddress config/verify-ens-contract-address
|
:verifyENSContractAddress config/verify-ens-contract-address
|
||||||
:verifyTransactionChainID config/verify-transaction-chain-id
|
:verifyTransactionChainID config/verify-transaction-chain-id
|
||||||
:wakuV2LightClient true
|
:wakuV2LightClient true
|
||||||
:previewPrivacy config/blank-preview?
|
:wakuV2Fleet config/fleet
|
||||||
:testNetworksEnabled config/test-networks-enabled?)))
|
:wakuV2EnableStoreConfirmationForMessagesSent false
|
||||||
|
:previewPrivacy config/blank-preview?
|
||||||
|
:testNetworksEnabled config/test-networks-enabled?)))
|
||||||
|
|
||||||
(defn strip-file-prefix
|
(defn strip-file-prefix
|
||||||
[path]
|
[path]
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user