Compare commits

...
Author SHA1 Message Date
Ibrahem Khalil 2009199c25 feat: Add internal link preview for communities (#18484) 2024-03-13 00:49:19 +02:00
Sean Hagstrom 103c4b4653 chore: decode emoji-hash and bio from contact payload (#19030) 2024-03-12 17:42:11 +00:00
Flavio Fraschetti 0828e9aa55 Fraschetti/18343 - Add contract test for wallet_getDerivedAddresses and move legacy code
Add contract test for wallet_getDerivedAddresses and move legacy code
2024-03-12 13:21:23 -03:00
Sean Hagstrom 0efdea6962 Feature: Ignore / Dismiss contact requests from contact profile (#19166)
* chore: add english translation for "contact request ignored"

* feature: integrate action to ignore contact request and display toast

* wip: default to showing "send contact request" after ignoring contact request
2024-03-12 13:48:21 +00:00
Sean Hagstrom d4c8e48441 Add action to remove contact inside contact action menu (#19168)
* chore: add english translation for "Remove contact"

* feature: integrate remove-contact acton in contact-profile action menu
2024-03-12 13:34:59 +00:00
Jamie Caprani 2931ae84ee chore(navigation): qualify wallet screen keywords (#18778) 2024-03-12 11:22:04 +00:00
Lungu Cristian 637efa24cf Clean up biometrics and standard-auth and add tests (#18756)
* ref(biometric): events using reg-event-fx & other

* test(biometric-events): show-message

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

* fix(biometrics): removed unnecessary event

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

* test(biometrics): tests & schemas for events

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

* ref(standard-auth): refactored authorize

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

* test(biometrics): fixed event tests

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

* ref(standard-auth): authorize using events

* feat(standard-auth): schemas and removed old auth

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

* test(standard-auth): added integration tests

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

* feat(biometric): added missing schema

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

* ref(biometrics): moved schemas to a separate file

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

* fix(biometric): pressing biometric quickly errors

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

* fix: removed namespaced keywords for errors

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

* ref: removed the use of vector cb for biometric fx

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

* fix: removed :maybe from fx schema

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

* ref: remove event-fx schema

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

* feat: added nested biometrics db keys

* fix: using ExceptionInfo for the error schema

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

* test: removed clearing fixture and small refactor

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

* fix: reset db password inside standard-authentication

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

* ref: use naming convention for effects

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

* ref: renamed not-canceled? to success?

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

* rev: removed biometrics schemas :(

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

* fix: removed set-in & fix on-close bug

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

* fix: onboarding biometric not triggered

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

* fix: invalid props bug on onboarding welcome

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

* fix: moved side effect cb call into effect

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

* test: moved integration test to new location

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

* fix: password input theme

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

* fix: disabled biometric not triggering fail when checking biometric

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

---------

Signed-off-by: Cristian Lungu <lungucristian95@gmail.com>
2024-03-12 12:14:56 +02:00
Jamie Caprani c57e5cd6db chore: improve share wallet test (#19107) 2024-03-12 08:44:59 +00:00
Parvesh Monu 604e232bda Implement alert banner (#19011) 2024-03-12 14:03:37 +05:30
Volodymyr Kozieiev e4997a2088 Root keys named :wallet/... moved as nested under :wallet root key (#19152) 2024-03-11 21:19:48 +00:00
Sean Hagstrom 459bf1621a Show toast after sending contact request (#19144)
* chore: add english translations for "Contact request sent"

* feature: add toast notification when sending a contact request
2024-03-11 10:10:50 +00:00
Sean Hagstrom ca9346a931 Implement reviewal of contact requests from contact profile (#19119)
* chore: add english translation for contact-request-review

* feature: integrate contact-request-review button

* tweak: render the locked-input label when provided

* tweak: allow locked-input component to grow in height

* chore: add english translation for "ignore"

* feature: add subscription for retrieving a pending contact-request by contact-id

* feature: integrate initial contact request review flow

* tweak: display send-message button on contact profile when contact-request-state is mutual

* tidy: refactor button-wrapper view to be button container-styles

* feature: add toast for accepting contact request
2024-03-11 09:43:18 +00:00
Mohsen 7065f4abd2 [#19101] feat: share contact profile (#19154) 2024-03-10 18:56:45 +03:00
Mohsen e283a72454 [#19048] feat: show contact QR code (#19139) 2024-03-09 00:36:24 +03:00
Ulises Manuel 3c6923963d [#18736] add address to watch using an ENS (#19043)
* Add capability to register an address based on an ENS

* update tests

* Check for existing addresses using an ENS
2024-03-08 12:20:41 -06:00
Mohsen 7a6714eeb2 [#18929] fix: no bottom space under the join button (#18987) 2024-03-08 19:24:02 +03:00
Alexander b3bebe1859 Update status-go version to fix the issue with peer syncing migration (#19127)
* Update `status-go` version to fix the issue with peer syncing migration

https://github.com/status-im/status-go/compare/8e8c1614...f9e7caa5

* Latest `commit-sha1`

* Fixes
2024-03-08 13:41:10 +01:00
Ulises Manuel ad546f9f14 [#18608] Immprove collectibles fetching performance (#18921)
* Add memoized versions to convert keys

* Add placeholder for SVG collectibles due to errors and warnings

* Add events to request collectibles per account

* Update subs to list all accounts collectibles evenly

* Update collectibles tab to pull new data when end is reached

* Use memoized version of key transformation
2024-03-07 12:05:45 -06:00
Mohsen 3145ecd6bf [#19037] feat: new design for manage nickname (#19085) 2024-03-07 15:23:07 +03:00
frank 669a232ad9 fix: peer exchange (#19082) 2024-03-07 18:10:17 +08:00
yqrashawn 29e69c54bd build: less node_modules recopy from nix (#19120) 2024-03-07 13:30:36 +08:00
flexsurfer 5fd0b27589 [#18985] Polish group details view (#19032) 2024-03-06 16:36:52 +01:00
Mohamed Javid 7d6b2ac87a [Feature] Wallet - Handle Blockchain Status (#18850)
This commit adds the feature to handle blockchain status signals from the status-go and shows a toast if the provider for any of the blockchains is down.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-03-06 20:59:52 +05:30
Jamie CapraniandYevheniia Berdnyk 93f488e61a chore(wallet): remove legacy network settings options (#18955)
* e2e: removed unused element

---------

Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-03-06 07:05:05 -08:00
Sean Hagstrom f7498ef81f Implement Contact Request flow in Contact Profile (#19039)
* chore: add send-contact-request to i18n translations

* feature: add send-contact-request button on contact profile

* chore: prop drill full-name and profile-picture for the context-tag inside drawer-top component

* chore: add english translation for contact-request-message-prompt text

* feature: integrate contact-request sheet

* tidy: subscribe to contact data inside contact-request view

* tidy: wrap callback with use-callback

* tweak: hide contact-request button if contact-request is already sent
2024-03-06 12:57:02 +00:00
Ibrahem Khalil f1834c6a15 Sort communities by currently active tab (#18812) 2024-03-06 13:13:58 +02:00
Mohamed Javid ffcca1aea3 [Chore] Remove POKT Sepolia and Goerli RPC URL (#19040)
This commit removes the POKT (Grove) URL for Sepolia and Goerli as POKT dropped support.
Now, we will use Infura RPC for Sepolia and Goerli as default.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-03-06 15:50:36 +05:30
Ibrahem Khalil 0937da9e50 Fix usage of ratom to fix wallet share (#18883) 2024-03-06 10:46:48 +02:00
yqrashawn 33e637ff71 fix(style): :resize-method is not avaliable on ios (#18914) 2024-03-06 15:25:43 +08:00
Parvesh Monu a538e2896e fix Blink of shell screen occurs when the Scan sync button is tapped (#19104) 2024-03-06 10:16:58 +05:30
flexsurfer c02cc5d391 The wrong UI is applied for 'sync code' section when light mode is en… (#19110) 2024-03-05 18:59:02 +01:00
Parvesh Monu 613e48ece3 fix the mention highlighted area is only updated after reopening the chat (#19076) 2024-03-05 21:06:22 +05:30
Sean Hagstrom f788d7bc85 [#19035] Add status tag for pending contact request to contact profile (#19075)
* chore: add english translation for contact-profile-request-pending

* feature: integrate status-tag for pending contact-request
2024-03-05 14:07:45 +00:00
Lungu Cristian 7415ebdc78 Updated placeholder for no pinned messages in chat (#18923)
* fix: same placeholder for chat & community pins

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

* fix: text linebreak

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

---------

Signed-off-by: Cristian Lungu <lungucristian95@gmail.com>
2024-03-05 15:47:48 +02:00
Alexander 58e9ae0334 Add peer syncing toggle in "Advanced settings" (#18906)
* Add peer syncing toggle in "Advanced settings"

* status-go-version.json

* Fixes
2024-03-05 12:59:06 +01:00
Sean Hagstrom e783deb5af [#18964] Support custom message when sending contact request (#18998)
* tweak: allow for optional message to be sent when making a contact request

* chore: migrate contact-request event handler from `rf/defn` to `rf/reg-event-fx`

* test: add tests for sending a contact request

* chore: make it easier to test on-success and on-error behaviour after sending a contact request

* tidy: use reframe fx for declaring json-rpc/call

* tidy: remove unused success event handler for send a contact request
2024-03-05 10:45:16 +00:00
Parvesh Monu e771d056a0 fix multiple set view-id events dispatched (#19083) 2024-03-05 11:50:00 +05:30
Omar Basem 62f68ff44b Fix: slide button (#18922)
* fix: slide button
2024-03-05 07:50:03 +04:00
Icaro Motta 5d1e1f8005 Make integration tests more enjoyable to use (#19025)
This commit brings numerous improvements to integration tests. The next step
will be to apply the same improvements to contract tests.

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

Improvements:

- Setting up the application and logged account per test is now done with an
  async test fixture, which is a very idiomatic way to solve this problem. No
  need anymore to write macros to wrap day8.re-frame.test/wait-for. The macros
  in test-helpers.integration will be removed once we apply the same
  improvements to contract tests.
- Integration test timeouts can be controlled per test, with a configurable,
  global default (60s).
- Now the integration test suite will fail-fast by default, i.e. a test failure
  short-circuits the entire suite immediately. This option can be overridden on
  a test-by-test basis. This improvement is very useful when investigating
  failures because the error will be shown on the spot, with no need to search
  backwards across lots of logs.
- Noisy messages from re-frame can be silenced with a test fixture. We can
  silence even more in the future if we remove the hardcoded printf call from
  C++ on every signal and control it with Clojure. We can disable most logs as
  well with the more direct (status-im.common.log/setup "ERROR") at the top of
  tests.integration-test.core. We can make verbosity even more convenient to
  control, but I think this should be designed outside this PR.
- Removed dependency on lib day8.re-frame/test for integration tests (see
  detailed explanation below).
- Each call to (our) wait-for can customize the timeout to process re-frame
  event IDs passed to it.
- Syntax is now flat, instead of being nested on every call to wait-for. You
  can now compose other async operations anywhere in a test.

Notes:

- promesa.core/do is essential in the integration test suite, as it makes sync &
  async operations play nice with each other without the developer having to
  promisify anything manually.
- There are lots of logs related to async storage ("unexpected token u in JSON at
  position..."). This isn't fixed yet.

Are we not going to use day8.re-frame.test?

We don't need this library in integration tests and we won't need it in contract
tests. Whether it will be useful after we remove it from integration and
contract tests is yet to be seen (probably not).

A few reasons:

- The async model of promises is well understood and battle tested. The one
  devised in the lib is poorly understood and rigid.
- There's basically no way to correctly integrate other async operations in the
  test, unless they can be fully controlled via re-frame events. For instance,
  how would you control timeouts? How would you retry in a test? How would
  forcefully delay an operation by a few seconds? These things are useful (to me
  at least) when developing integration/contract tests.
- Every call to day8.re-frame.test/wait-for forces you to nest code one more
  level. Code readability suffers from that choice.
- Have you ever looked up the implementation of wait-for? It's quite convoluted.
  One could say the source code is not that important, but many times I had to
  look it up because I couldn't understand the async model they built with their
  macro approach. The de facto primitive in JS for asynchronicity is promises,
  and we fully leverage it in this PR.
- The lib has an interesting macro run-test-sync, but we have no usage for it. I
  used it in status-mobile for a while. At one point, all event unit tests for
  the Activity Center used it (e.g. commit
  08fb0de7b0), but I replaced them with the
  simpler pure function style.
2024-03-04 22:38:42 -03:00
Jamie Caprani 191c876f47 chore(wallet): some minor cleanups: move sheets to appropriate level, remove unused rf event, improve one rf event api (#18895) 2024-03-04 12:34:21 -08:00
Ibrahem Khalil 0be66e28c1 Fix collectible/token icon and name on addresses for permissions screen (#18897) 2024-03-04 18:34:10 +02:00
Nazarii F fcdd6c5a79 Added destructuring section to new-guidelines.md (#18731)
Adds a section explaining the use cases of destructuring function parameters to
improve code style and reduce the chance of bugs.
2024-03-04 11:38:50 -03:00
Icaro Motta 27e177f18b Account selection: Use bottom sheet component (#18919)
Use bottom sheet component as designed in
Figma https://www.figma.com/file/h9wo4GipgZURbqqr1vShFN/Communities-for-Mobile?type=design&node-id=16409-98076&mode=design&t=jrVNb3JnWNurJwP8-0

- Fixes no animation when closing Addresses For Permissions modal:
  https://github.com/status-im/status-mobile/issues/18617
- Fixes drawer is always expanded:
  https://github.com/status-im/status-mobile/issues/18619

Additionally:

- Fixed incorrect code passing a function instance to a style prop, which leads
  to incorrect appearance for settings.category.reorder.view/view.
- Optimized Reagent a little bit by extracting functions that need to close over
  the community ID to the mount phase. That way, we avoid regenerating function
  instances on every re-render and Reagent can avoid a bit of re-work.

The challenge was to make the scrollable content work inside a
bottom sheet, while supporting the designs for a fixed (always visible) header
and footer.
2024-03-04 09:23:30 -03:00
Lungu Cristian f8cd14296f Add Promesa to simplify working with promises (#18767)
* added promesa (clj)

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

* ref(resize): using promesa instead of passing cb

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

---------

Signed-off-by: Cristian Lungu <lungucristian95@gmail.com>
2024-03-04 13:59:52 +02:00
Parvesh Monu 851eb6ea8f fix settings navigation (#19080) 2024-03-04 16:06:59 +05:30
Volodymyr Kozieiev 7754460acc Malli schemas added to components (#18949) 2024-03-01 21:03:35 +00:00
Brian Sztamfater 7d55c98e0a feat: update transaction confirmation page to support bridging transactions (#18887) 2024-03-01 16:26:45 -03:00
Mohsen 0e9847f2c3 [#18963] feat: actions UI for stranger contact profile (#19028) 2024-03-01 16:14:05 +03:00
Sean Hagstrom 1aef3106bd Fix chat UI element colors (#18941)
* chore: add community color subscription

* fix: use configured chat color for chat ui and fallback to community color

* test: ensure community-color subscription returns the community color

* tidy: use resolve-color function instead of custom-color function

* revise: rename community-color to customization-color and default non-community channel color to turquoise
2024-03-01 10:46:29 +00:00
Lungu Cristian a4b973970b Fix account edit confirmation button (#18930)
* fix: confirm button not visible

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

* fix: edit account btn text

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

* fix: removed bottom-action? prop

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

* fix: removed unused on-focus and on-blur props

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

* ref: using floating-button-page

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

* fix: linting error

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

* fix: hide btn when disabled and keyboard hidden

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

* fix: react warning and header height (again)

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

* fix: replace padding prop with style

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

* fix: addressed review comments

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

* chore: removed redundant :f> due to new reagent compiler

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

---------

Signed-off-by: Cristian Lungu <lungucristian95@gmail.com>
2024-03-01 12:00:32 +02:00
Omar Basem abd2b43ce6 Wallet: finalize kp (#18991)
Wallet: finalize kp
2024-03-01 08:09:36 +04:00
BalogunofAfrica ac78dea8ef fix: use blacklist for parallax (#18971) 2024-02-29 17:13:06 +01:00
Mohsen b1f0d1c3d7 [#18865] fix: separate edit bio and set bio, update number of profile name characters (#18892) 2024-02-29 18:28:09 +03:00
flexsurfer da22063308 Error on login with touch ID enabled #19055 (#19057) 2024-02-29 14:56:44 +01:00
flexsurfer c15084fffa fix watch address input field (#19051) 2024-02-29 14:40:01 +01:00
Omar Basem d637f69a45 Revert account origin sheet (#19034)
Revert account origin sheet (#19034)
2024-02-29 10:13:15 +04:00
268 changed files with 4914 additions and 2981 deletions
+1
View File
@@ -26,6 +26,7 @@
malli.generator malli.generator
malli.transform malli.transform
malli.util malli.util
promesa.core p
schema.core schema
status-im.feature-flags ff
taoensso.timbre log}}
+9
View File
@@ -0,0 +1,9 @@
{:lint-as {promesa.core/-> clojure.core/->
promesa.core/->> clojure.core/->>
promesa.core/as-> clojure.core/as->
promesa.core/let clojure.core/let
promesa.core/plet clojure.core/let
promesa.core/loop clojure.core/loop
promesa.core/recur clojure.core/recur
promesa.core/with-redefs clojure.core/with-redefs
promesa.core/doseq clojure.core/doseq}}
+31 -28
View File
@@ -22,34 +22,37 @@
:multi-lhs-hang]
:fn-map
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
"h/describe-skip" :arg1-body
"h/describe-only" :arg1-body
"h/test" :arg1-body
"h/test-skip" :arg1-body
"h/test-only" :arg1-body
"global.describe" :arg1-body
"global.test" :arg1-body
"list-comp" :binding
"defview" :arg1-body
"letsubs" :binding
"with-let" "let"
"reg-event-fx" :arg1-pair
"reg-fx" :arg1-pair
"testing" :arg1-body
"deftest-sub" :arg1-body
"wait-for" :arg1-body
"with-deps-check" :arg1-body
"schema/=>" :arg1-body
"->" [:noarg1-body
{:list {:constant-pair? false :force-nl? false}
:next-inner-restore [[:list :constant-pair?]]}]
"set!" "reset!"
"assoc-when" "assoc"
"assoc-some" "assoc"
"conj-when" "conj"
"conj-some" "conj"}
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
"h/describe-skip" :arg1-body
"h/describe-only" :arg1-body
"h/test" :arg1-body
"h/test-skip" :arg1-body
"h/test-only" :arg1-body
"test/async" :arg1-body
"test/use-fixtures" :arg1-body
"global.describe" :arg1-body
"global.test" :arg1-body
"list-comp" :binding
"defview" :arg1-body
"letsubs" :binding
"with-let" "let"
"reg-event-fx" :arg1-pair
"reg-fx" :arg1-pair
"testing" :arg1-body
"deftest-sub" :arg1-body
"h/integration-test" :arg1-body
"wait-for" :arg1-body
"with-deps-check" :arg1-body
"schema/=>" :arg1-body
"->" [:noarg1-body
{:list {:constant-pair? false :force-nl? false}
:next-inner-restore [[:list :constant-pair?]]}]
"set!" "reset!"
"assoc-when" "assoc"
"assoc-some" "assoc"
"conj-when" "conj"
"conj-some" "conj"}
:style-map
{:no-comma {:map {:comma? false}}
+5 -3
View File
@@ -331,13 +331,14 @@ shadow-server:##@ Start shadow-cljs in server mode for watching
_test-clojure: export TARGET := clojure
_test-clojure: export WATCH ?= false
_test-clojure: status-go-library
_test-clojure:
ifeq ($(WATCH), true)
yarn install && \
yarn node-pre-gyp rebuild && \
yarn shadow-cljs compile mocks && \
nodemon --exec "yarn shadow-cljs compile test && node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO" -e cljs
else
yarn install && \
yarn node-pre-gyp rebuild && \
yarn shadow-cljs compile mocks && \
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js "$$SHADOW_OUTPUT_TO"
@@ -350,8 +351,9 @@ test: _test-clojure
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: status-go-library
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
yarn install
yarn node-pre-gyp rebuild
rm -f target/test/test.js
yarn shadow-cljs compile mocks && \
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
@@ -1888,6 +1888,36 @@ void _InitLogging(const FunctionCallbackInfo<Value>& args) {
delete c;
}
void _RestoreAccountAndLogin(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for RestoreAccountAndLogin")));
return;
}
// Check the argument types
if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'RestoreAccountAndLogin'")));
return;
}
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;
// Call exported Go function, which returns a C string
char *c = RestoreAccountAndLogin(arg0);
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "multiAccountGenerateAndDeriveAddresses", _MultiAccountGenerateAndDeriveAddresses);
@@ -1945,6 +1975,7 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "connectionChange", _ConnectionChange);
NODE_SET_METHOD(exports, "pollSignal", _PollSignal);
NODE_SET_METHOD(exports, "initLogging", _InitLogging);
NODE_SET_METHOD(exports, "restoreAccountAndLogin", _RestoreAccountAndLogin);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, init)
+148 -130
View File
@@ -90,20 +90,20 @@
},
{
"path": "cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3",
"path": "cider/cider-nrepl/0.31.0/cider-nrepl-0.31.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "5ae0efd9377a5e60c084bdaf4a2ce094f759ce23",
"sha256": "0drxf9nm23i1pcgrkwbcr09msq37csilzww38709add0hz8spjhq"
"sha1": "1f28a4a834a7a46cf24def971b1a705a6795c73a",
"sha256": "0h4pyzy8rzzh567khvimw2cs8jr640kqxgaxvbfx1s5yfp56fka2"
}
},
{
"path": "cider/piggieback/0.4.1/piggieback-0.4.1",
"path": "cider/piggieback/0.5.2/piggieback-0.5.2",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "0a02a3e2ecd7a126ab60d8a44793342f20ced79b",
"sha256": "142vl5np33akcrnn6pksi0rjfsmmi528villxsj6cwcndvybiw4m"
"sha1": "ecfd5c286a85db3f059e75c37fca5722d9e26f79",
"sha256": "1ps9yf3cxmlm447hqkidjb5xry90n0wl3jk0jn28fagq31lzylkl"
}
},
@@ -251,15 +251,6 @@
}
},
{
"path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1",
"sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf"
}
},
{
"path": "com/google/errorprone/error_prone_annotations/2.15.0/error_prone_annotations-2.15.0",
"host": "https://repo1.maven.org/maven2",
@@ -306,11 +297,11 @@
},
{
"path": "com/google/javascript/closure-compiler-unshaded/v20230411/closure-compiler-unshaded-v20230411",
"path": "com/google/javascript/closure-compiler-unshaded/v20230802/closure-compiler-unshaded-v20230802",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "2f5d7ab921f9cc07ffeb4e1c0f156f164c650eeb",
"sha256": "0gphdrrhr88bcqa1scndachvhbayh7m11zm9hcsmvzn9bw72pabw"
"sha1": "0a2498a4d45bf5896042f31da0cd30c5e7b415af",
"sha256": "0jvgqq0gnvm4jw2zac4677ds05klvsjalszdzcq3nw8g7fjyjv2x"
}
},
@@ -333,38 +324,11 @@
},
{
"path": "commons-codec/commons-codec/1.15/commons-codec-1.15",
"path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "49d94806b6e3dc933dacbd8acb0fdbab8ebd1e5d",
"sha256": "0qzd8v96j4x7jjcfpvvdh9ar1xhwxpxi2rh51nzhj0br7bbgdsdk"
}
},
{
"path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0",
"sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54"
}
},
{
"path": "commons-io/commons-io/2.11.0/commons-io-2.11.0",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "a2503f302b11ebde7ebc3df41daebe0e4eea3689",
"sha256": "020946yakki3qzc652arfndzi594drxanidz9bawbb6vhxnjy6wn"
}
},
{
"path": "compojure/compojure/1.5.2/compojure-1.5.2",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439",
"sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf"
"sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1",
"sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf"
}
},
@@ -404,6 +368,42 @@
}
},
{
"path": "commons-codec/commons-codec/1.15/commons-codec-1.15",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "49d94806b6e3dc933dacbd8acb0fdbab8ebd1e5d",
"sha256": "0qzd8v96j4x7jjcfpvvdh9ar1xhwxpxi2rh51nzhj0br7bbgdsdk"
}
},
{
"path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0",
"sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54"
}
},
{
"path": "commons-io/commons-io/2.11.0/commons-io-2.11.0",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "a2503f302b11ebde7ebc3df41daebe0e4eea3689",
"sha256": "020946yakki3qzc652arfndzi594drxanidz9bawbb6vhxnjy6wn"
}
},
{
"path": "compojure/compojure/1.5.2/compojure-1.5.2",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439",
"sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf"
}
},
{
"path": "crypto-equality/crypto-equality/1.0.1/crypto-equality-1.0.1",
"host": "https://repo.clojars.org",
@@ -449,6 +449,15 @@
}
},
{
"path": "funcool/promesa/11.0.678/promesa-11.0.678",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "0ee1690ba74b2609c2d85b51edacad13046a18e2",
"sha256": "1wif8nwdbpchwg56fz47ymjnflmva0fzy0bw1s6bacnac472pmza"
}
},
{
"path": "hiccup/hiccup/1.0.5/hiccup-1.0.5",
"host": "https://repo.clojars.org",
@@ -504,11 +513,11 @@
},
{
"path": "io/undertow/undertow-core/2.2.4.Final/undertow-core-2.2.4.Final",
"path": "io/undertow/undertow-core/2.3.10.Final/undertow-core-2.3.10.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "78650b4029dd9280c4769d9425b5559f12cb83bf",
"sha256": "1brpkd2l98byf76jga6hj5drv5sj2d93lxlq2xz0rxpqyqas1xm4"
"sha1": "96d1d5ca6406a75a285b95ea8f4b39e0fb2d707e",
"sha256": "1s1m5hfhmfr7jsp4bn4c6fhdbgiz72mz0a96494nyhfa0b4lql8l"
}
},
@@ -594,11 +603,11 @@
},
{
"path": "nrepl/nrepl/1.0.0/nrepl-1.0.0",
"path": "nrepl/nrepl/0.9.0/nrepl-0.9.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "f47774c43493efdc879d36b95ebd67ea0d9c890a",
"sha256": "1fx5ssmixgqmklliw0ng8fjz41kkhys56x8dbwv9yqrfzws9f2x3"
"sha1": "49beada131959f08f9a20899affbd1b10c03a668",
"sha256": "1phak0479s27ffw9wzz7pi8cqqs6ipsm15dhgw9szxxcfhx529qa"
}
},
@@ -611,15 +620,6 @@
}
},
{
"path": "org/apache/ant/ant/1.10.11/ant-1.10.11",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "b875cd48a0bc955ae9c5c477ad991e1f26fb24d2",
"sha256": "0m07pifkdpwghpp8wvqh14sbxazmjbkkpsfakw6ixq5apfdvih48"
}
},
{
"path": "org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11",
"host": "https://repo1.maven.org/maven2",
@@ -630,11 +630,11 @@
},
{
"path": "org/babashka/sci/0.7.38/sci-0.7.38",
"host": "https://repo.clojars.org",
"path": "org/apache/ant/ant/1.10.11/ant-1.10.11",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "ef2d8c74065b9a7d685a11bff017676db308a923",
"sha256": "04pkxwcgkd1p4f4rszsr6pp18fl0vni1az47a390llrhyyrjcckn"
"sha1": "b875cd48a0bc955ae9c5c477ad991e1f26fb24d2",
"sha256": "0m07pifkdpwghpp8wvqh14sbxazmjbkkpsfakw6ixq5apfdvih48"
}
},
@@ -647,6 +647,15 @@
}
},
{
"path": "org/babashka/sci/0.7.38/sci-0.7.38",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "ef2d8c74065b9a7d685a11bff017676db308a923",
"sha256": "04pkxwcgkd1p4f4rszsr6pp18fl0vni1az47a390llrhyyrjcckn"
}
},
{
"path": "org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0",
"host": "https://repo1.maven.org/maven2",
@@ -737,15 +746,6 @@
}
},
{
"path": "org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "533ce2bdbb7925db781449abb6527af1e6c5e782",
"sha256": "0js19lw8bp9gym3pn47h867vhf65j18qc6x1pfn883vkwyasm18l"
}
},
{
"path": "org/clojure/google-closure-library-third-party/0.0-20230227-c7c0a541/google-closure-library-third-party-0.0-20230227-c7c0a541",
"host": "https://repo1.maven.org/maven2",
@@ -755,6 +755,15 @@
}
},
{
"path": "org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "533ce2bdbb7925db781449abb6527af1e6c5e782",
"sha256": "0js19lw8bp9gym3pn47h867vhf65j18qc6x1pfn883vkwyasm18l"
}
},
{
"path": "org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0",
"host": "https://repo1.maven.org/maven2",
@@ -782,15 +791,6 @@
}
},
{
"path": "org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "692882a35d7b50947d6e4852fba8a51d8d5e3646",
"sha256": "08fzw3srrppgq1d11sh1ghnyvi24ixa10kbqsncc7xyx7fybcs0k"
}
},
{
"path": "org/clojure/tools.analyzer.jvm/1.2.2/tools.analyzer.jvm-1.2.2",
"host": "https://repo1.maven.org/maven2",
@@ -800,6 +800,15 @@
}
},
{
"path": "org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "692882a35d7b50947d6e4852fba8a51d8d5e3646",
"sha256": "08fzw3srrppgq1d11sh1ghnyvi24ixa10kbqsncc7xyx7fybcs0k"
}
},
{
"path": "org/clojure/tools.cli/1.0.206/tools.cli-1.0.206",
"host": "https://repo1.maven.org/maven2",
@@ -828,11 +837,11 @@
},
{
"path": "org/clojure/tools.reader/1.3.6/tools.reader-1.3.6",
"path": "org/clojure/tools.reader/1.3.7/tools.reader-1.3.7",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "927809dcb44fa726e4969d993e3e733636d95ebb",
"sha256": "1q5q7fmshybvp55f6qys8i5sbzfaix5v9f9b55dkbhv55hgv7l8i"
"sha1": "c60dfd3d79cbc5ec6264ba45c14b8d4c9b6708b2",
"sha256": "1mr0qx3gw1myfls07vrx3arwsi5n95b2lwk74ijpj0z3lzpzlj7m"
}
},
@@ -846,38 +855,38 @@
},
{
"path": "org/jboss/logging/jboss-logging/3.4.1.Final/jboss-logging-3.4.1.Final",
"path": "org/jboss/logging/jboss-logging/3.4.3.Final/jboss-logging-3.4.3.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "40fd4d696c55793e996d1ff3c475833f836c2498",
"sha256": "1f7f4kjn3v6vibhgsr3k8hl0r2xq0c2rbcl82dx0bqg5jdyqgzlf"
"sha1": "c4bd7e12a745c0e7f6cf98c45cdcdf482fd827ea",
"sha256": "0jdcziqbdzmah981zv3q88k2zrnclr2h1k3h3vjn002m9p54qchb"
}
},
{
"path": "org/jboss/threads/jboss-threads/3.1.0.Final/jboss-threads-3.1.0.Final",
"path": "org/jboss/threads/jboss-threads/3.5.0.Final/jboss-threads-3.5.0.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "9b260c0302f637a84a52d3d118214a3c59217615",
"sha256": "0yc0p71y7yjhqjhkvqqi9xqgljavp3aslnik2k7dppbxnkrnlff9"
"sha1": "dd23d4788b3eafe9597ef3fe028e46ceb293ba8d",
"sha256": "1cchp54dw1578my27siim3h5jbf240aq8q6xd3z2b1ajgxxbcl71"
}
},
{
"path": "org/jboss/xnio/xnio-api/3.8.0.Final/xnio-api-3.8.0.Final",
"path": "org/jboss/xnio/xnio-api/3.8.8.Final/xnio-api-3.8.8.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "e2c29acf42ac6f42c34f0b74ba089e3f3d1b2394",
"sha256": "041qnvb74bkgmfxyd23vdl26il55cmfbhi6a4bm3fcmyrpapjfjl"
"sha1": "1ba9c8b9a8dea1c6cd656155943e6d4c2c631fa7",
"sha256": "0wvqdcbardi55l77aw5404qgw70384hw155xvc66shn7l6z8h6bh"
}
},
{
"path": "org/jboss/xnio/xnio-nio/3.8.0.Final/xnio-nio-3.8.0.Final",
"path": "org/jboss/xnio/xnio-nio/3.8.8.Final/xnio-nio-3.8.8.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "90c57dcf7f8c846b4da331d0e6e048c39842c92a",
"sha256": "1zndnb5648wqw23gj80zjqk3yd8gq6grqhz9n4zrcqixx1z586jf"
"sha1": "a5d2faf8d02e0a0bb9e9eabca8e38173cb640331",
"sha256": "0pxw2iv1q1yzk39knc650rg4vflsyjzhf07mwm2s5aqn5h82sk3i"
}
},
@@ -909,11 +918,20 @@
},
{
"path": "org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36",
"path": "org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "6c62681a2f655b49963a5983b8b0950a6120ae14",
"sha256": "1h512ry8g0nriazg3dqzs6s96502a77drw8vq26nfya97rg5gvyk"
"sha1": "7cf2726fdcfbc8610f9a71fb3ed639871f315340",
"sha256": "0v1b7iydpnh2rvyzqvqbqm19vr2qva8icq84690bppnpr06r6608"
}
},
{
"path": "org/slf4j/slf4j-nop/2.0.9/slf4j-nop-2.0.9",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "fa0627049304bf501bf6a0e4d1416bcaec9a72a9",
"sha256": "10vdg9qkailjbzmf5mfnv328675swmnf1x3g9v7ymhxs29xkc4jn"
}
},
@@ -927,11 +945,11 @@
},
{
"path": "org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final",
"path": "org/wildfly/common/wildfly-common/1.5.4.Final/wildfly-common-1.5.4.Final",
"host": "https://repo1.maven.org/maven2",
"jar": {
"sha1": "8eba40cfe86bcfcc223551e75201e6e7574c7c36",
"sha256": "17rkkm9dqbxdzpamwl9jr8z285awsj6hzpavzmc87wcz9469hp5b"
"sha1": "735ceee5616d5143bac1bc740e444697073c002f",
"sha256": "0sp48y3q7bmp3bjb7a6fpz8gb7ssizvxlw5wdv2xwa6mifpkrnlz"
}
},
@@ -944,15 +962,6 @@
}
},
{
"path": "reagent/reagent/1.2.0/reagent-1.2.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "1b9a181b5c7ed3557768d2ea0c66f5616aef5e97",
"sha256": "0scvkzfqjs613z10rngh7427v3pxdqablf0fcl65pbpkzz16wgav"
}
},
{
"path": "re-com/re-com/2.8.0/re-com-2.8.0",
"host": "https://repo.clojars.org",
@@ -962,15 +971,6 @@
}
},
{
"path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207",
"sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i"
}
},
{
"path": "re-frame/re-frame/1.3.0/re-frame-1.3.0",
"host": "https://repo.clojars.org",
@@ -998,6 +998,24 @@
}
},
{
"path": "reagent/reagent/1.2.0/reagent-1.2.0",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "1b9a181b5c7ed3557768d2ea0c66f5616aef5e97",
"sha256": "0scvkzfqjs613z10rngh7427v3pxdqablf0fcl65pbpkzz16wgav"
}
},
{
"path": "refactor-nrepl/refactor-nrepl/3.9.1/refactor-nrepl-3.9.1",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "f949af92dd1d6fef59d7447bd0cb62118e34eca1",
"sha256": "0dml9yvjmji6xk2sk3cdmkvvnh13rw29szxxl363hap8yg28xcs1"
}
},
{
"path": "ring-cors/ring-cors/0.1.8/ring-cors-0.1.8",
"host": "https://repo.clojars.org",
@@ -1035,11 +1053,11 @@
},
{
"path": "thheller/shadow-cljs/2.25.0/shadow-cljs-2.25.0-aot",
"path": "thheller/shadow-cljs/2.26.2/shadow-cljs-2.26.2-aot",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "013921db91ce4a3616aec9c72c1832a014a0fece",
"sha256": "0ks380z7h8i2ylirvjgmlicq9jjpz9w71gjv521h4xs5fb273cl0"
"sha1": "ab6b31649cb03e352369698781207db4f6da6d5f",
"sha256": "0mh28nykpillkym7hvplrr7vy5hn6a2ymafyf4yfl5y2kfx4yq42"
}
},
@@ -1053,11 +1071,11 @@
},
{
"path": "thheller/shadow-undertow/0.3.1/shadow-undertow-0.3.1",
"path": "thheller/shadow-undertow/0.3.3/shadow-undertow-0.3.3",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "9be444bea4037bb80b451cc52a8e80359c4c45be",
"sha256": "174s2rdxvp7d4jg9kvzjadps42bdsbi05rs2pjy5i0ssq9n23zwa"
"sha1": "ba377c3b70fd942b3ca7e38f055412a441626711",
"sha256": "10w2slj4znm93j0qq3ldj9hj0i7a50vbnmn6kv8i77fakikdjc48"
}
},
+27 -25
View File
@@ -8,8 +8,8 @@ borkdude/edamame/1.3.23/edamame-1.3.23.jar
borkdude/sci.impl.reflector/0.0.1/sci.impl.reflector-0.0.1.jar
camel-snake-kebab/camel-snake-kebab/0.4.3/camel-snake-kebab-0.4.3.jar
cheshire/cheshire/5.11.0/cheshire-5.11.0.jar
cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3.jar
cider/piggieback/0.4.1/piggieback-0.4.1.jar
cider/cider-nrepl/0.31.0/cider-nrepl-0.31.0.jar
cider/piggieback/0.5.2/piggieback-0.5.2.jar
clj-kondo/clj-kondo/2023.09.07/clj-kondo-2023.09.07.jar
cljs-bean/cljs-bean/1.9.0/cljs-bean-1.9.0.jar
clout/clout/2.1.2/clout-2.1.2.jar
@@ -26,35 +26,36 @@ com/github/javaparser/javaparser-core/3.25.3/javaparser-core-3.25.3.jar
com/google/auto/value/auto-value-annotations/1.6/auto-value-annotations-1.6.jar
com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar
com/google/code/gson/gson/2.9.1/gson-2.9.1.jar
com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar
com/google/errorprone/error_prone_annotations/2.15.0/error_prone_annotations-2.15.0.jar
com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar
com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.jar
com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar
com/google/javascript/closure-compiler-unshaded/v20230411/closure-compiler-unshaded-v20230411.jar
com/google/javascript/closure-compiler-unshaded/v20230802/closure-compiler-unshaded-v20230802.jar
com/google/protobuf/protobuf-java/3.21.12/protobuf-java-3.21.12.jar
com/google/re2j/re2j/1.3/re2j-1.3.jar
commons-codec/commons-codec/1.15/commons-codec-1.15.jar
commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar
commons-io/commons-io/2.11.0/commons-io-2.11.0.jar
compojure/compojure/1.5.2/compojure-1.5.2.jar
com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar
com/taoensso/encore/3.68.0/encore-3.68.0.jar
com/taoensso/timbre/6.3.1/timbre-6.3.1.jar
com/taoensso/truss/1.11.0/truss-1.11.0.jar
com/taoensso/tufte/2.6.3/tufte-2.6.3.jar
commons-codec/commons-codec/1.15/commons-codec-1.15.jar
commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar
commons-io/commons-io/2.11.0/commons-io-2.11.0.jar
compojure/compojure/1.5.2/compojure-1.5.2.jar
crypto-equality/crypto-equality/1.0.1/crypto-equality-1.0.1.jar
crypto-random/crypto-random/1.2.1/crypto-random-1.2.1.jar
day8/re-frame/test/0.1.5/test-0.1.5.jar
expound/expound/0.9.0/expound-0.9.0.jar
fipp/fipp/0.6.26/fipp-0.6.26.jar
funcool/promesa/11.0.678/promesa-11.0.678.jar
hiccup/hiccup/1.0.5/hiccup-1.0.5.jar
http-kit/http-kit/2.2.0/http-kit-2.2.0.jar
instaparse/instaparse/1.4.0/instaparse-1.4.0.jar
io/aviso/pretty/1.4.4/pretty-1.4.4.jar
io/methvin/directory-watcher/0.17.1/directory-watcher-0.17.1.jar
io/replikativ/datalog-parser/0.2.25/datalog-parser-0.2.25.jar
io/undertow/undertow-core/2.2.4.Final/undertow-core-2.2.4.Final.jar
io/undertow/undertow-core/2.3.10.Final/undertow-core-2.3.10.Final.jar
javax/annotation/jsr250-api/1.0/jsr250-api-1.0.jar
javax/servlet/servlet-api/2.5/servlet-api-2.5.jar
javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar
@@ -64,12 +65,12 @@ mvxcvi/arrangement/2.1.0/arrangement-2.1.0.jar
net/cgrand/macrovich/0.2.1/macrovich-0.2.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/nrepl/1.0.0/nrepl-1.0.0.jar
nrepl/nrepl/0.9.0/nrepl-0.9.0.jar
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.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/babashka/sci/0.7.38/sci-0.7.38.jar
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
org/babashka/sci.impl.types/0.0.2/sci.impl.types-0.0.2.jar
org/babashka/sci/0.7.38/sci-0.7.38.jar
org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.jar
org/clojure/clojure/1.11.1/clojure-1.11.1.jar
org/clojure/clojurescript/1.11.60/clojurescript-1.11.60.jar
@@ -80,41 +81,42 @@ org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.jar
org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar
org/clojure/data.json/2.4.0/data.json-2.4.0.jar
org/clojure/data.priority-map/1.1.0/data.priority-map-1.1.0.jar
org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541.jar
org/clojure/google-closure-library-third-party/0.0-20230227-c7c0a541/google-closure-library-third-party-0.0-20230227-c7c0a541.jar
org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541.jar
org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0.jar
org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar
org/clojure/test.check/1.1.1/test.check-1.1.1.jar
org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0.jar
org/clojure/tools.analyzer.jvm/1.2.2/tools.analyzer.jvm-1.2.2.jar
org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0.jar
org/clojure/tools.cli/1.0.206/tools.cli-1.0.206.jar
org/clojure/tools.logging/1.1.0/tools.logging-1.1.0.jar
org/clojure/tools.macro/0.1.5/tools.macro-0.1.5.jar
org/clojure/tools.reader/1.3.6/tools.reader-1.3.6.jar
org/clojure/tools.reader/1.3.7/tools.reader-1.3.7.jar
org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar
org/jboss/logging/jboss-logging/3.4.1.Final/jboss-logging-3.4.1.Final.jar
org/jboss/threads/jboss-threads/3.1.0.Final/jboss-threads-3.1.0.Final.jar
org/jboss/xnio/xnio-api/3.8.0.Final/xnio-api-3.8.0.Final.jar
org/jboss/xnio/xnio-nio/3.8.0.Final/xnio-nio-3.8.0.Final.jar
org/jboss/logging/jboss-logging/3.4.3.Final/jboss-logging-3.4.3.Final.jar
org/jboss/threads/jboss-threads/3.5.0.Final/jboss-threads-3.5.0.Final.jar
org/jboss/xnio/xnio-api/3.8.8.Final/xnio-api-3.8.8.Final.jar
org/jboss/xnio/xnio-nio/3.8.8.Final/xnio-nio-3.8.8.Final.jar
org/jspecify/jspecify/0.2.0/jspecify-0.2.0.jar
org/msgpack/msgpack/0.6.12/msgpack-0.6.12.jar
org/ow2/asm/asm/9.4/asm-9.4.jar
org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar
org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar
org/slf4j/slf4j-nop/2.0.9/slf4j-nop-2.0.9.jar
org/wildfly/client/wildfly-client-config/1.0.1.Final/wildfly-client-config-1.0.1.Final.jar
org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final.jar
org/wildfly/common/wildfly-common/1.5.4.Final/wildfly-common-1.5.4.Final.jar
prismatic/schema/1.1.7/schema-1.1.7.jar
reagent/reagent/1.2.0/reagent-1.2.0.jar
re-com/re-com/2.8.0/re-com-2.8.0.jar
refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
re-frame/re-frame/1.3.0/re-frame-1.3.0.jar
re-frisk-remote/re-frisk-remote/1.6.0/re-frisk-remote-1.6.0.jar
re-frisk/sente/1.15.0/sente-1.15.0.jar
reagent/reagent/1.2.0/reagent-1.2.0.jar
refactor-nrepl/refactor-nrepl/3.9.1/refactor-nrepl-3.9.1.jar
ring-cors/ring-cors/0.1.8/ring-cors-0.1.8.jar
ring/ring-codec/1.2.0/ring-codec-1.2.0.jar
ring/ring-core/1.9.6/ring-core-1.9.6.jar
thheller/shadow-client/1.3.3/shadow-client-1.3.3.jar
thheller/shadow-cljs/2.25.0/shadow-cljs-2.25.0-aot.jar
thheller/shadow-cljs/2.26.2/shadow-cljs-2.26.2-aot.jar
thheller/shadow-cljsjs/0.0.22/shadow-cljsjs-0.0.22.jar
thheller/shadow-undertow/0.3.1/shadow-undertow-0.3.1.jar
thheller/shadow-undertow/0.3.3/shadow-undertow-0.3.3.jar
thheller/shadow-util/0.7.0/shadow-util-0.7.0.jar
tigris/tigris/0.1.2/tigris-0.1.2.jar
+10
View File
@@ -53,6 +53,14 @@ copyNodeModules() {
# Find files that were modified and should cause a re-copying of node modules.
# Some files are generated/modified by build processes and should be ignored.
#
# react-native/ReactCommon/react/renderer/components/rncore/*
# generated at runtime by react-native
# related code https://github.com/facebook/react-native/blob/v0.72.5/packages/react-native/ReactCommon/React-rncore.podspec#L19
#
# react-native-config/ios/ReactNativeConfig/GeneratedDotEnv.m
# generated at runtime by react-native-config
# related code https://github.com/lugg/react-native-config/blob/v1.5.0/react-native-config.podspec#L52
findFilesNewerThan() {
local sentinel="${1}"
local dir="${2}"
@@ -61,6 +69,8 @@ findFilesNewerThan() {
-not -ipath "*/*android/build/*" -prune \
-not -ipath "*/xcuserdata/*" -prune \
-not -ipath "*/scripts/.packager.env" \
-not -path "*/node_modules/react-native/ReactCommon/react/renderer/components/rncore/*" \
-not -path "*/node_modules/react-native-config/ios/ReactNativeConfig/GeneratedDotEnv.m" \
-print
}
+1
View File
@@ -10,6 +10,7 @@
[com.cognitect/transit-cljs "0.8.280"]
[camel-snake-kebab "0.4.3"]
[metosin/malli "0.13.0"]
[funcool/promesa "11.0.678"]
;; Dev dependencies
[refactor-nrepl "3.9.1"]
-4
View File
@@ -3,7 +3,6 @@
["eth-phishing-detect" :as eth-phishing-detect]
[clojure.string :as string]
[legacy.status-im.bottom-sheet.events :as bottom-sheet]
[legacy.status-im.browser.eip3085 :as eip3085]
[legacy.status-im.browser.eip3326 :as eip3326]
[legacy.status-im.browser.permissions :as browser.permissions]
[legacy.status-im.browser.webview-ref :as webview-ref]
@@ -443,9 +442,6 @@
(= method "wallet_switchEthereumChain")
(eip3326/handle-switch-ethereum-chain cofx dapp-name id message-id (first params))
(= method "wallet_addEthereumChain")
(eip3085/handle-add-ethereum-chain cofx dapp-name id message-id (first params))
:else
{:browser/call-rpc [payload
#(re-frame/dispatch [:browser.callback/call-rpc
-38
View File
@@ -2,10 +2,6 @@
;(`wallet_addEthereumChain`)
(ns legacy.status-im.browser.eip3085
(:require
[clojure.string :as string]
[legacy.status-im.network.core :as network]
[legacy.status-im.ui.screens.browser.eip3085.sheet :as sheet]
[legacy.status-im.utils.random :as random]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[taoensso.timbre :as log]
@@ -40,37 +36,3 @@
:message "User rejected the request."}}
:dispatch [:bottom-sheet/hide-old]})
(rf/defn handle-add-ethereum-chain
{:events [:eip3085/handle-add-ethereum-chain]}
[{{:networks/keys [networks] :as db} :db :as cofx}
dapp-name id message-id
{:keys [chainId blockExplorerUrls chainName iconUrls nativeCurrency rpcUrls] :as params}]
(let [manage {:name {:value chainName}
:symbol {:value (:symbol nativeCurrency)}
:url {:value (first rpcUrls)}
:network-id {:value chainId}
:chain {:value :custom}}]
(if (network/valid-manage? manage)
(let [{:keys [name url chain network-id symbol]} manage
random-id (string/replace (random/id) "-" "")
network (network/new-network random-id
(:value name)
(:value symbol)
(:value url)
(:value chain)
(:value network-id))
new-networks (assoc networks random-id network)
params (assoc params
:new-networks new-networks
:id id
:new-network network)]
(if (network/chain-id-available? networks network)
{:dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[sheet/permissions-panel dapp-name message-id params])}]}
(send-success-call-to-bridge cofx id message-id)))
{:browser/send-to-bridge {:type constants/web3-send-async-callback
:messageId message-id
:error {:code -32602
:message "invalid network parameters"}}})))
+3 -3
View File
@@ -45,12 +45,12 @@
(query-fn (comp participant-set :public-key) (vals all-contacts))))
(defn get-all-contacts-in-group-chat
[members admins contacts {:keys [public-key preferred-name name] :as current-account}]
[members admins contacts {:keys [public-key preferred-name name display-name] :as current-account}]
(let [current-contact (some->
current-account
(select-keys [:name :preferred-name :public-key :images])
(select-keys [:name :preferred-name :public-key :images :compressed-key])
(set/rename-keys {:name :alias :preferred-name :name})
(assoc :primary-name (or preferred-name name)))
(assoc :primary-name (or display-name preferred-name name)))
all-contacts (cond-> contacts
current-contact
(assoc public-key current-contact))]
@@ -29,37 +29,39 @@
(testing "transforms messages from RPC response"
(is
(= {:last-message {:quoted-message nil
:outgoing-status nil
:command-parameters nil
:link-previews []
:content {:sticker nil
:rtl? nil
:ens-name nil
:parsed-text nil
:response-to nil
:chat-id nil
:image nil
:line-count nil
:links nil
:text nil}
:outgoing false}
(= {:last-message {:quoted-message nil
:outgoing-status nil
:command-parameters nil
:link-previews []
:status-link-previews []
:content {:sticker nil
:rtl? nil
:ens-name nil
:parsed-text nil
:response-to nil
:chat-id nil
:image nil
:line-count nil
:links nil
:text nil}
:outgoing false}
:message nil
:reply-message {:quoted-message nil
:outgoing-status nil
:command-parameters nil
:link-previews []
:content {:sticker nil
:rtl? nil
:ens-name nil
:parsed-text nil
:response-to nil
:chat-id nil
:image nil
:line-count nil
:links nil
:text nil}
:outgoing false}}
:reply-message {:quoted-message nil
:outgoing-status nil
:command-parameters nil
:link-previews []
:status-link-previews []
:content {:sticker nil
:rtl? nil
:ens-name nil
:parsed-text nil
:response-to nil
:chat-id nil
:image nil
:line-count nil
:links nil
:text nil}
:outgoing false}}
(-> raw-notification
store/<-rpc
(select-keys [:last-message :message :reply-message])))))
+33 -3
View File
@@ -16,13 +16,41 @@
:community-id :communityId
:clock-value :clock})))
(defn- <-status-link-previews-rpc
[preview]
(-> preview
(update :community
set/rename-keys
{:communityId :community-id
:displayName :display-name
:membersCount :members-count
:activeMembersCount :active-members-count})
(update-in [:community :banner] set/rename-keys {:dataUri :data-uri})
(update-in [:community :icon] set/rename-keys {:dataUri :data-uri})))
(defn ->status-link-previews-rpc
[preview]
(-> preview
(update :community
set/rename-keys
{:community-id :communityId
:display-name :displayName
:members-count :membersCount
:active-members-count :activeMembersCount})
(update-in [:community :banner] set/rename-keys {:data-uri :dataUri})
(update-in [:community :icon] set/rename-keys {:data-uri :dataUri})))
(defn- <-link-preview-rpc
[preview]
(update preview :thumbnail set/rename-keys {:dataUri :data-uri}))
(-> preview
(update :thumbnail set/rename-keys {:dataUri :data-uri})
(update :favicon set/rename-keys {:dataUri :data-uri})))
(defn ->link-preview-rpc
[preview]
(update preview :thumbnail set/rename-keys {:data-uri :dataUri}))
(-> preview
(update :thumbnail set/rename-keys {:data-uri :dataUri})
(update :favicon set/rename-keys {:data-uri :dataUri})))
(defn <-rpc
[message]
@@ -53,8 +81,10 @@
:new :new?
:albumImagesCount :album-images-count
:displayName :display-name
:linkPreviews :link-previews})
:linkPreviews :link-previews
:statusLinkPreviews :status-link-previews})
(update :link-previews #(map <-link-preview-rpc %))
(update :status-link-previews #(map <-status-link-previews-rpc %))
(update :quoted-message
set/rename-keys
{:parsedText :parsed-text
@@ -37,7 +37,19 @@
:compressed-key "c"
:timestamp 3
:link-previews [{:thumbnail {:url "http://localhost"
:data-uri "data:image/png"}}]}
:data-uri "data:image/png"}
:favicon nil}]
:status-link-previews [{:url "http://localhost"
:community {:community-id "0x01"
:display-name "Test Comm"
:members-count 12
:active-members-count 12
:banner
{:data-uri
"data:image/png"}
:icon
{:data-uri
"data:image/png"}}}]}
message {:id message-id
:whisperTimestamp 1
:parsedText "parsed-text"
@@ -61,5 +73,17 @@
:timestamp 3
:outgoingStatus "sending"
:linkPreviews [{:thumbnail {:url "http://localhost"
:dataUri "data:image/png"}}]}]
:dataUri "data:image/png"}
:favicon nil}]
:statusLinkPreviews [{:url "http://localhost"
:community {:communityId "0x01"
:displayName "Test Comm"
:membersCount 12
:activeMembersCount 12
:banner
{:dataUri
"data:image/png"}
:icon
{:dataUri
"data:image/png"}}}]}]
(is (= expected (m/<-rpc message))))))
+2 -3
View File
@@ -37,7 +37,6 @@
[react-native.core :as rn]
[react-native.permissions :as permissions]
[react-native.platform :as platform]
[status-im.common.biometric.events :as biometric]
status-im.common.serialization
status-im.common.standard-authentication.events
[status-im.common.theme.core :as theme]
@@ -120,7 +119,7 @@
:content (i18n/label :t/biometric-auth-confirm-message)
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
:on-accept #(biometric/authenticate nil {:on-fail on-biometric-auth-fail})
:on-accept #(rf/dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}])
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])})))
(rf/defn on-return-from-background
@@ -142,7 +141,7 @@
#(when-let [chat-id (:current-chat-id db)]
{:dispatch [:chat/mark-all-as-read chat-id]})
#(when requires-bio-auth
(biometric/authenticate % {:on-fail on-biometric-auth-fail})))))
{:dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}]}))))
(rf/defn on-going-in-background
[{:keys [db now]}]
@@ -13,15 +13,14 @@
(native-module/logout)))
(rf/defn initialize-app-db
[{{:keys [keycard initials-avatar-font-file]
:biometric/keys [supported-type]
:network/keys [type]}
[{{:keys [keycard initials-avatar-font-file biometrics]
:network/keys [type]}
:db}]
{:db (assoc db/app-db
:network/type type
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometric/supported-type supported-type
:biometrics biometrics
:syncing nil)})
(rf/defn logout-method
@@ -46,6 +45,7 @@
[_]
;; we need to disable notifications before starting the logout process
{:effects/push-notifications-disable nil
:dispatch [:alert-banners/remove-all]
:dispatch-later [{:ms 100
:dispatch [::logout-method
{:auth-method keychain/auth-method-none
+1 -132
View File
@@ -1,11 +1,6 @@
(ns legacy.status-im.network.core
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.navigation.events :as navigation]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[clojure.string :as string]))
(def url-regex
#"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)")
@@ -14,12 +9,6 @@
[url]
(boolean (re-matches url-regex (str url))))
(def default-manage
{:name {:value ""}
:url {:value ""}
:symbol {:value ""}
:chain {:value :mainnet}})
(defn validate-string
[{:keys [value]}]
{:value value
@@ -56,123 +45,3 @@
[current-networks network]
(let [chain-id (get-in network [:config :NetworkId])]
(every? #(not= chain-id (get-in % [1 :config :NetworkId])) current-networks)))
(defn get-network
[{:keys [db]} network-id]
(get-in db [:networks/networks network-id]))
(rf/defn set-input
{:events [::input-changed]}
[{:keys [db]} input-key value]
{:db (-> db
(update-in [:networks/manage input-key] assoc :value value)
(update-in [:networks/manage] validate-manage))})
;; No edit functionality actually implemented
(rf/defn edit
{:events [::add-network-pressed]}
[{db :db}]
{:db (assoc db :networks/manage (validate-manage default-manage))
:dispatch [:navigate-to :edit-network]})
(rf/defn connect-success
{:events [::connect-success]}
[_ network-id]
{:ui/show-confirmation
{:title (i18n/label :t/close-app-title)
:content (i18n/label :t/logout-app-content)
:confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(re-frame/dispatch [::save-network-settings-pressed network-id])
:on-cancel nil}})
(rf/defn connect-failure
{:events [::connect-failure]}
[_ reason]
{:effects.utils/show-popup
{:title (i18n/label :t/error)
:content (str reason)}})
(rf/defn connect
{:events [::connect-network-pressed]}
[{:keys [db] :as cofx} network-id]
(if (get-in db [:networks/networks network-id :config])
(connect-success cofx network-id)
(connect-failure cofx "A network with the specified id doesn't exist")))
(rf/defn delete
{:events [::delete-network-pressed]}
[{:keys [db]} network]
(let [current-network? (= (:networks/current-network db) network)]
(if (or current-network?
(not (get-in db [:networks/networks network])))
{:ui/show-error (i18n/label :t/delete-network-error)}
{:ui/show-confirmation {:title (i18n/label :t/delete-network-title)
:content (i18n/label :t/delete-network-confirmation)
:confirm-button-text (i18n/label :t/delete)
:on-accept #(re-frame/dispatch [::remove-network-confirmed
network])
:on-cancel nil}})))
(rf/defn save-network-settings
{:events [::save-network-settings-pressed]}
[{:keys [db] :as cofx} network]
{:db (assoc db :networks/current-network network)
:json-rpc/call [{:method "settings_saveSetting"
:params [:networks/current-network network]
:on-success #(re-frame/dispatch [:logout])}]})
(rf/defn remove-network
{:events [::remove-network-confirmed]}
[{:keys [db] :as cofx} network]
(let [networks (dissoc (:networks/networks db) network)]
{:db (assoc db :networks/networks networks)
:json-rpc/call [{:method "settings_saveSetting"
:params [:networks/networks (vals networks)]
:on-success #(re-frame/dispatch [:navigate-back])}]}))
(defn new-network
[random-id network-name sym upstream-url chain-type chain-id]
(let [data-dir (str "/ethereum/" (name chain-type) "_rpc")
config {:NetworkId (or (when chain-id (int chain-id))
(chain/chain-keyword->chain-id chain-type))
:DataDir data-dir
:UpstreamConfig {:Enabled true
:URL upstream-url}}]
{:id random-id
:name network-name
:symbol sym
:config config}))
(rf/defn save
{:events [::save-network-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{{:networks/keys [manage networks] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
(if (valid-manage? manage)
;; rename network-id from UI to chain-id
(let [{:keys [name url chain network-id symbol]} manage
random-id (string/replace (random-id-generator) "-" "")
network (new-network random-id
(:value name)
(:value symbol)
(:value url)
(:value chain)
(:value network-id))
custom-chain-type? (= :custom (:value chain))
new-networks (assoc networks random-id network)]
(if (or (not custom-chain-type?)
(chain-id-available? networks network))
{:db (-> db
(dissoc :networks/manage)
(assoc :networks/networks new-networks))
:json-rpc/call [{:method "settings_saveSetting"
:params [:networks/networks (vals new-networks)]
:on-success #(re-frame/dispatch [:navigate-back])}]}
{:ui/show-error "chain-id already defined"}))
{:ui/show-error "invalid network parameters"}))
(rf/defn open-network-details
{:events [::network-entry-pressed]}
[cofx network]
(navigation/navigate-to cofx :network-details {:networks/selected-network network}))
-130
View File
@@ -31,38 +31,6 @@
(testing "an https url not on the default port"
(is (network.core/valid-rpc-url? "https://valid.something.else:65323"))))
(deftest new-network-test
(let [actual (network.core/new-network "randomid"
"network-name"
"network-symbol"
"upstream-url"
:mainnet
nil)]
(is (= {:id "randomid"
:name "network-name"
:symbol "network-symbol"
:config {:NetworkId 1
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL "upstream-url"}}}
actual))))
(deftest new-network-id-test
(let [actual (network.core/new-network "randomid"
"network-name"
"network-symbol"
"upstream-url"
:mainnet
"5777")]
(is (= {:id "randomid"
:name "network-name"
:symbol "network-symbol"
:config {:NetworkId 5777
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL "upstream-url"}}}
actual))))
(deftest valid-manage-test
(testing "a valid manage"
(is (network.core/valid-manage? {:url {:value "http://valid.com"}
@@ -92,101 +60,3 @@
:name {:value "valid"}
:symbol {:value ""}
:chain {:value "valid"}})))))
(deftest set-input-test
(testing "it updates and validate a field"
(is
(= {:db {:networks/manage {:url {:value "http://valid.com"
:error false}
:name {:value ""
:error true}
:symbol {:value "symbol"
:error false}
:chain {:value "mainnet"
:error false}
:network-id {:value nil
:error false}}}}
(network.core/set-input {:db {:networks/manage {:url {:value "something"
:error true}
:name {:value ""
:error false}
:symbol {:value "symbol"
:error false}
:chain {:value "mainnet"
:error false}}}}
:url
"http://valid.com")))))
(deftest not-save-invalid-url
(testing "it does not save a network with an invalid url"
(is
(:ui/show-error (network.core/save {:random-id-generator (constantly "random")
:db {:networks/manage {:url {:value "wrong"}
:chain {:value "1"}
:name {:value "empty"}}
:profile/profile {}}})))))
(deftest save-valid-network
(testing "save a valid network"
(let [fx (network.core/save
{:random-id-generator (constantly "random-id")
:db {:networks/manage {:url {:value "http://valid.com"}
:chain {:value :mainnet}
:symbol {:value "symbol"}
:name {:value "valid"}}
:profile/profile {}
:networks/networks {"random2"
{:id "random2"
:name "network-name"
:symbol "symbol"
:config {:NetworkId 1
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig
{:Enabled true
:URL "upstream-url"}}}}}})]
(is (= "settings_saveSetting" (:method (first (:json-rpc/call fx)))))
(is (nil? (:networks/manage (:db fx))))
(testing "and check that it has an id with `-` and the correct mainnet NetworkId"
(is (= 1 (get-in fx [:db :networks/networks "randomid" :config :NetworkId])))))))
(deftest not-save-custom-chain-with-non-unique-id
(testing "it does not save a custom chain with network-id already defined"
(let [result (network.core/save
{:random-id-generator (constantly "already-defined")
:db {:networks/manage {:url {:value "http://valid.com"}
:chain {:value :custom}
:name {:value "valid"}
:network-id {:value 1}}
:profile/profile {}
:networks/networks {"random"
{:id "random"
:name "network-name"
:config {:NetworkId 1
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig
{:Enabled true
:URL "upstream-url"}}}}}})]
(is (:ui/show-error result)))))
(deftest save-valid-network-with-unique-chain-id-check
(testing "save a valid network with chain-id not already defined"
(let [fx (network.core/save
{:random-id-generator (constantly "random")
:db {:networks/manage {:url {:value "http://valid.com"}
:chain {:value :mainnet}
:name {:value "valid"}
:symbol {:value "symbol"}
:network-id {:value 5}}
:profile/profile {}
:networks/networks {"randomid"
{:id "randomid"
:name "network-name"
:symbol "symbol"
:config {:NetworkId 3
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig
{:Enabled true
:URL "upstream-url"}}}}}})]
(is (= "settings_saveSetting" (:method (first (:json-rpc/call fx)))))
(is (nil? (:networks/manage (:db fx))))
(is (get-in fx [:db :networks/networks "random"])))))
-39
View File
@@ -1,39 +0,0 @@
(ns legacy.status-im.subs.networks
(:require
[re-frame.core :as re-frame]
[status-im.config :as config]
[utils.ethereum.chain :as chain]))
(defn- filter-networks
[network-type]
(fn [network]
(let [chain-id (chain/network->chain-id network)
testnet? (chain/testnet? chain-id)
custom? (:custom? network)]
(case network-type
:custom custom?
:mainnet (and (not custom?) (not testnet?))
:testnet (and (not custom?) testnet?)))))
(defn- label-networks
[default-networks]
(fn [network]
(let [custom? (not (default-networks (:id network)))]
(assoc network :custom? custom?))))
(re-frame/reg-sub
:get-networks
:<- [:networks/networks]
(fn [networks]
(let [networks (map (label-networks (into #{} (map :id config/default-networks)))
(sort-by :name (vals networks)))
types [:mainnet :testnet :custom]]
(zipmap
types
(map #(filter (filter-networks %) networks) types)))))
(re-frame/reg-sub
:manage-network-valid?
:<- [:networks/manage]
(fn [manage]
(not-any? :error (vals manage))))
+2 -1
View File
@@ -5,7 +5,6 @@
legacy.status-im.subs.ens
legacy.status-im.subs.keycard
legacy.status-im.subs.mailservers
legacy.status-im.subs.networks
legacy.status-im.subs.stickers
[re-frame.core :as re-frame]))
@@ -23,6 +22,7 @@
(reg-root-key-sub :peers-count :peers-count)
(reg-root-key-sub :peers-summary :peers-summary)
(reg-root-key-sub :web3-node-version :web3-node-version)
(reg-root-key-sub :alert-banners :alert-banners)
;;keycard
(reg-root-key-sub :keycard :keycard)
@@ -100,6 +100,7 @@
;;; Link previews
(reg-root-key-sub :link-previews-whitelist :link-previews-whitelist)
(reg-root-key-sub :chat/link-previews :chat/link-previews)
(reg-root-key-sub :chat/status-link-previews :chat/status-link-previews)
;;commands
(reg-root-key-sub :commands/select-account :commands/select-account)
@@ -13,37 +13,21 @@
(re-frame/dispatch event))
(defn- normal-mode-settings-data
[{:keys [network-name
current-log-level
[{:keys [current-log-level
light-client-enabled?
transactions-management-enabled?
current-fleet
webview-debug
test-networks-enabled?
is-goerli-enabled?]}]
is-goerli-enabled?
peer-syncing-enabled?]}]
(keep
identity
[{:size :small
:title (i18n/label :t/network)
:accessibility-label :network-button
:container-margin-top 8
:on-press
#(re-frame/dispatch [:navigate-to :network-settings])
:accessory :text
:accessory-text network-name
:chevron true}
{:size :small
:title (i18n/label :t/network-info)
:accessibility-label :network-button
:container-margin-top 8
:on-press
#(re-frame/dispatch [:navigate-to :network-info])
:chevron true}
{:size :small
:title (i18n/label :t/log-level)
:accessibility-label :log-level-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :log-level-settings])
#(re-frame/dispatch [:open-modal :log-level-settings])
:accessory :text
:accessory-text current-log-level
:chevron true}
@@ -51,7 +35,7 @@
:title (i18n/label :t/fleet)
:accessibility-label :fleet-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :fleet-settings])
#(re-frame/dispatch [:open-modal :fleet-settings])
:accessory :text
:accessory-text current-fleet
:chevron true}
@@ -66,14 +50,14 @@
:accessibility-label :rpc-usage-info
:container-margin-top 8
:on-press
#(re-frame/dispatch [:navigate-to :rpc-usage-info])
#(re-frame/dispatch [:open-modal :rpc-usage-info])
:chevron true}
{:size :small
:title (i18n/label :t/peers-stats)
:accessibility-label :peers-stats
:container-margin-top 8
:on-press
#(re-frame/dispatch [:navigate-to :peers-stats])
#(re-frame/dispatch [:open-modal :peers-stats])
:chevron true}
{:size :small
:title (i18n/label :t/light-client-enabled)
@@ -119,11 +103,19 @@
#(re-frame/dispatch [:profile.settings/toggle-goerli-test-network])
:accessory :switch
:active is-goerli-enabled?}
{:size :small
:title "Peer syncing"
:accessibility-label :peer-syncing
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:profile.settings/toggle-peer-syncing])
:accessory :switch
:active peer-syncing-enabled?}
{:size :small
:title (i18n/label :t/set-currency)
:accessibility-label :wallet-change-currency
:on-press #(hide-sheet-and-dispatch
[:navigate-to :currency-settings])
[:open-modal :currency-settings])
:chevron true}]))
(defn- flat-list-data
@@ -142,20 +134,20 @@
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
webview-debug [:profile/webview-debug]
network-name [:network-name]
transactions-management-enabled? [:wallet-legacy/transactions-management-enabled?]
current-log-level [:log-level/current-log-level]
current-fleet [:fleets/current-fleet]]
current-fleet [:fleets/current-fleet]
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
[list/flat-list
{:data (flat-list-data
{:network-name network-name
:current-log-level current-log-level
{:current-log-level current-log-level
:transactions-management-enabled? transactions-management-enabled?
:light-client-enabled? light-client-enabled?
:current-fleet current-fleet
:dev-mode? false
:webview-debug webview-debug
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?})
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
:key-fn (fn [_ i] (str i))
:render-fn render-item}]))
@@ -85,9 +85,7 @@
:accessibility-label :share-community-link
:type :secondary
:on-press #(debounce/throttle-and-dispatch
[(if can-invite?
::communities/invite-people-confirmation-pressed
::communities/share-community-confirmation-pressed) @user-pk
[::communities/share-community-confirmation-pressed @user-pk
selected]
3000)}
(i18n/label (if can-invite? :t/invite :t/share))]}]]))))
@@ -1,12 +0,0 @@
(ns legacy.status-im.ui.screens.network.edit-network.styles)
(def edit-network-view
{:flex 1
:margin-horizontal 16
:margin-vertical 15})
(def bottom-container
{:flex-direction :row
:padding-vertical 4})
(def container {:flex 1})
@@ -1,72 +0,0 @@
(ns legacy.status-im.ui.screens.network.edit-network.views
(:require
[legacy.status-im.network.core :as network]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.network.edit-network.styles :as styles]
[re-frame.core :as re-frame]
[utils.i18n :as i18n])
(:require-macros [legacy.status-im.utils.views :as views]))
(defn- render-network-type
[type _ _ manage-network]
(let [name (case type
:mainnet (i18n/label :t/mainnet-network)
:goerli (i18n/label :t/goerli-network)
:custom (i18n/label :t/custom))]
[list.item/list-item
{:title name
:accessory :radio
:active (= (get-in manage-network [:chain :value]) type)
:on-press #(re-frame/dispatch [::network/input-changed :chain type])}]))
(views/defview edit-network
[]
(views/letsubs [manage-network [:networks/manage]
is-valid? [:manage-network-valid?]]
(let [custom? (= (get-in manage-network [:chain :value]) :custom)]
[react/keyboard-avoiding-view {:flex 1}
[react/scroll-view
[react/view styles/edit-network-view
[react/view {:padding-vertical 8}
[quo/text-input
{:label (i18n/label :t/name)
:placeholder (i18n/label :t/specify-name)
:default-value (get-in manage-network [:name :value])
:on-change-text #(re-frame/dispatch [::network/input-changed :name %])
:auto-focus true}]]
[react/view {:padding-vertical 8}
[quo/text-input
{:label (i18n/label :t/symbol)
:placeholder (i18n/label :t/specify-symbol)
:default-value (get-in manage-network [:symbol :value])
:on-change-text #(re-frame/dispatch [::network/input-changed :symbol %])
:auto-focus true}]]
[react/view {:padding-vertical 8}
[quo/text-input
{:label (i18n/label :t/rpc-url)
:placeholder (i18n/label :t/specify-rpc-url)
:default-value (get-in manage-network [:url :value])
:on-change-text #(re-frame/dispatch [::network/input-changed :url %])}]]]
[quo/list-header (i18n/label :t/network-chain)]
[list/flat-list
{:data [:mainnet :goerli :custom]
:key-fn (fn [_ i] (str i))
:render-data manage-network
:render-fn render-network-type}]
(when custom?
[react/view styles/edit-network-view
[quo/text-input
{:label (i18n/label :t/network-id)
:placeholder (i18n/label :t/specify-network-id)
:on-change-text #(re-frame/dispatch [::network/input-changed :network-id %])}]])]
[react/view styles/bottom-container
[react/view {:flex 1}]
[quo/button
{:after :main-icons/next
:type :secondary
:disabled (not is-valid?)
:on-press #(re-frame/dispatch [::network/save-network-pressed])}
(i18n/label :t/save)]]])))
@@ -1,47 +0,0 @@
(ns legacy.status-im.ui.screens.network.network-details.views
(:require
[legacy.status-im.network.core :as network]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.network.styles :as st]
[legacy.status-im.ui.screens.network.views :as network-settings]
[re-frame.core :as re-frame]
[utils.debounce :refer [throttle-and-dispatch]]
[utils.i18n :as i18n])
(:require-macros [legacy.status-im.utils.views :as views]))
(views/defview network-details
[]
(views/letsubs [{:keys [networks/selected-network]} [:get-screen-params]
current-network [:networks/current-network]
networks [:get-networks]]
(let [{:keys [id name config]} selected-network
connected? (= id current-network)
custom? (seq (filter #(= (:id %) id) (:custom networks)))]
[:<>
[react/view {:flex 1}
[network-settings/network-badge
{:name name
:connected? connected?}]
(when-not connected?
[react/touchable-highlight
{:on-press #(throttle-and-dispatch [::network/connect-network-pressed id] 1000)}
[react/view st/connect-button-container
[react/view
{:style st/connect-button
:accessibility-label :network-connect-button}
[react/text {:style st/connect-button-label}
(i18n/label :t/connect)]]
[react/i18n-text
{:style st/connect-button-description
:key :connecting-requires-login}]]])
[react/view (st/network-config-container)
[react/text
{:style st/network-config-text
:accessibility-label :network-details-text}
config]]]
(when custom?
[react/view st/bottom-container
[react/view {:flex 1}
[quo/button {:on-press #(re-frame/dispatch [::network/delete-network-pressed id])}
(i18n/label :t/delete)]]])])))
@@ -1,90 +0,0 @@
(ns legacy.status-im.ui.screens.network.styles
(:require
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.utils.styles :as styles]))
(def wrapper
{:flex 1})
(def badge-name-text
{:font-size 17})
(styles/def badge-connected-text
{:color colors/gray
:ios {:margin-top 5}})
(def connect-button-container
{:margin-top 8
:margin-bottom 16
:margin-horizontal 16})
(def connect-button
{:height 52
:align-items :center
:justify-content :center
:background-color colors/blue
:border-radius 8
:ios {:opacity 0.9}})
(def connect-button-label
{:color colors/white-persist
:font-size 17})
(def connect-button-description
{:color colors/gray
:margin-top 8
:height 20})
(styles/defn network-config-container
[]
{:height 160
:margin-top 8
:padding-top 16
:padding-left 16
:margin-horizontal 16
:background-color colors/gray-lighter
:ios {:border-radius 9
:opacity 0.9}
:android {:border-radius 4}})
(styles/def network-config-text
{:font-size 17
:ios {:opacity 0.8}
:android {:opacity 0.4}})
(defn network-icon
[connected? size]
{:width size
:height size
:border-radius (/ size 2)
:background-color (if connected? colors/blue colors/gray-lighter)
:align-items :center
:justify-content :center})
(def network-badge
{:height 88
:padding-left 16
:flex-direction :row
:align-items :center})
(styles/def network-item
{:flex-direction :row
:align-items :center
:padding-horizontal 16
:ios {:height 64}
:android {:height 56}})
(def network-item-name-text
{:font-size 17})
(def network-item-connected-text
{:color colors/gray
:font-size 14
:margin-top 6})
(def bottom-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})
(def container {:flex 1})
@@ -1,71 +0,0 @@
(ns legacy.status-im.ui.screens.network.views
(:require
[legacy.status-im.network.core :as network]
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.icons.icons :as icons]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.components.topbar :as topbar]
[legacy.status-im.ui.screens.network.styles :as styles]
[re-frame.core :as re-frame]
[utils.i18n :as i18n])
(:require-macros [legacy.status-im.utils.views :as views]))
(defn- network-icon
[connected? size]
[react/view (styles/network-icon connected? size)
[icons/icon :main-icons/network {:color (if connected? colors/white-persist colors/gray)}]])
(defn network-badge
[& [{:keys [name connected?]}]]
[react/view styles/network-badge
[network-icon connected? 56]
[react/view {:padding-left 16}
[react/text {:style styles/badge-name-text}
(or name (i18n/label :t/new-network))]
(when connected?
[react/i18n-text
{:style styles/badge-connected-text
:key :connected}])]])
(def mainnet?
#{"mainnet" "mainnet_rpc"})
(defn render-network
[{:keys [id name] :as network} _ _ current-network]
(let [connected? (= id current-network)]
[list.item/list-item
{:on-press #(re-frame/dispatch [::network/network-entry-pressed network])
:icon :main-icons/network
:icon-bg-color (if connected? colors/blue colors/gray-lighter)
:icon-color (if connected? colors/white-persist colors/gray)
:title name
:subtitle (when connected? (i18n/label :t/connected))
:chevron true}]))
(views/defview network-settings
[]
(views/letsubs [current-network [:networks/current-network]
networks [:get-networks]]
[:<>
[topbar/topbar
{:title (i18n/label :t/network-settings)
:right-accessories
[{:icon :main-icons/add
:on-press #(re-frame/dispatch [::network/add-network-pressed])}]}]
[react/view styles/wrapper
[list/section-list
{:sections [{:title (i18n/label :t/main-networks)
:key :mainnet
:data (:mainnet networks)}
{:title (i18n/label :t/test-networks)
:key :testnet
:data (:testnet networks)}
{:title (i18n/label :t/custom-networks)
:key :custom
:data (:custom networks)}]
:key-fn :id
:default-separator? true
:render-data current-network
:render-fn render-network}]]]))
@@ -1,84 +0,0 @@
(ns legacy.status-im.ui.screens.network-info.views
(:require
[legacy.status-im.ethereum.decode :as decode]
[legacy.status-im.ui.components.react :as react]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.common.json-rpc.events :as json-rpc]
[utils.datetime :as datetime]))
(defn get-block
[block callback]
(json-rpc/call
{:method "eth_getBlockByNumber"
:params [block false]
:on-success callback
:on-error #(js/alert (str "can't fetch latest block" %))}))
(defn to-date
[timestamp]
(datetime/timestamp->long-date
(* 1000 timestamp)))
(defn check-lag
[]
(let [latest-block (reagent/atom nil)
last-loaded-block (reagent/atom nil)
on-press
(fn []
(get-block
"latest"
(fn [res]
(reset! latest-block res)
(get-block
(str "0x"
(native-module/number-to-hex
@(re-frame/subscribe [:ethereum/current-block])))
(fn [res]
(reset! last-loaded-block res))))))]
(fn []
[react/view
{:style {:flex 1
:margin-horizontal 16}}
(if-not @latest-block
[react/text
{:on-press on-press}
"PRESS TO REFRESH"]
[react/text
{:on-press on-press}
(let [latest-block-number
(decode/uint (:number @latest-block))
latest-block-timestamp
(decode/uint (:timestamp @latest-block))
last-loaded-block-number
(decode/uint (:number @last-loaded-block))
last-loaded-block-timestamp
(decode/uint (:timestamp @last-loaded-block))]
(str "Latest block number: "
latest-block-number
"\n"
"Latest block time: "
(to-date latest-block-timestamp)
"\n"
"Last loaded block: "
last-loaded-block-number
"\n"
"Last loaded block time: "
(to-date last-loaded-block-timestamp)
"\n"
"Seconds diff: "
(- latest-block-timestamp
last-loaded-block-timestamp)
"\n"
"Blocks diff: " (- latest-block-number
last-loaded-block-number)
"\n"
"PRESS TO REFRESH"))])])))
(defn network-info
[]
[check-lag])
@@ -102,7 +102,7 @@
:chevron true
:icon :main-icons/username}
registrar
(assoc :on-press #(re-frame/dispatch [:navigate-to :ens-main registrar])))]
(assoc :on-press #(re-frame/dispatch [:open-modal :ens-main registrar])))]
[list.item/list-item
{:title (i18n/label :t/contacts)
:icon :main-icons/in-contacts
@@ -112,7 +112,7 @@
(str active-contacts-count)
(i18n/label :t/none))
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :contacts-list])}]
:on-press #(re-frame/dispatch [:open-modal :contacts-list])}]
[react/view {:padding-top 16}
[quo/list-header (i18n/label :t/settings)]]
[list.item/list-item
@@ -122,71 +122,71 @@
:chevron true
:accessory (when mnemonic
[components.common/counter {:size 22} 1])
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security])}]
:on-press #(re-frame/dispatch [:open-modal :privacy-and-security])}]
(when config/quo-preview-enabled?
[list.item/list-item
{:icon :main-icons/appearance
:title "Quo Preview"
:accessibility-label :appearance-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :quo-preview])}])
:on-press #(re-frame/dispatch [:open-modal :quo-preview])}])
(when config/quo-preview-enabled?
[list.item/list-item
{:icon :main-icons/appearance
:title "Status IM Components"
:accessibility-label :status-im-common-components
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :status-im-preview])}])
:on-press #(re-frame/dispatch [:open-modal :status-im-preview])}])
[list.item/list-item
{:icon :main-icons/appearance
:title (i18n/label :t/appearance)
:accessibility-label :appearance-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :appearance])}]
:on-press #(re-frame/dispatch [:open-modal :appearance])}]
[list.item/list-item
{:icon :main-icons/notification
:title (i18n/label :t/notifications)
:accessibility-label :notifications-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :notifications])}]
:on-press #(re-frame/dispatch [:open-modal :notifications])}]
[list.item/list-item
{:icon :main-icons/mobile
:title (i18n/label :t/sync-settings)
:accessibility-label :sync-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :sync-settings])}]
:on-press #(re-frame/dispatch [:open-modal :sync-settings])}]
(when keycard-pairing
[list.item/list-item
{:icon :main-icons/keycard
:title (i18n/label :t/keycard)
:accessibility-label :keycard-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :keycard-settings])}])
:on-press #(re-frame/dispatch [:open-modal :keycard-settings])}])
[list.item/list-item
{:icon :main-icons/settings-advanced
:title (i18n/label :t/advanced)
:accessibility-label :advanced-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :advanced-settings])}]
:on-press #(re-frame/dispatch [:open-modal :advanced-settings])}]
[list.item/list-item
{:icon :main-icons/help
:title (i18n/label :t/need-help)
:accessibility-label :help-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :help-center])}]
:on-press #(re-frame/dispatch [:open-modal :help-center])}]
[list.item/list-item
{:icon :main-icons/info
:title (i18n/label :t/about-app)
:accessibility-label :about-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :about-app])}]
:on-press #(re-frame/dispatch [:open-modal :about-app])}]
(when local-pairing-mode-enabled?
[list.item/list-item
{:icon :i/mobile
:title (i18n/label :t/syncing)
:accessibility-label :syncing
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :settings-syncing])}])
:on-press #(re-frame/dispatch [:open-modal :settings-syncing])}])
[react/view {:padding-vertical 24}
[list.item/list-item
{:icon :main-icons/log-out
@@ -24,10 +24,6 @@
[legacy.status-im.ui.screens.link-previews-settings.views :as link-previews-settings]
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
[legacy.status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[legacy.status-im.ui.screens.network-info.views :as network-info]
[legacy.status-im.ui.screens.network.edit-network.views :as edit-network]
[legacy.status-im.ui.screens.network.network-details.views :as network-details]
[legacy.status-im.ui.screens.network.views :as network]
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
[legacy.status-im.ui.screens.offline-messaging-settings.edit-mailserver.views :as edit-mailserver]
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
@@ -227,18 +223,6 @@
;;TODO dynamic title
:options {:insets {:top? true}}
:component dapps-permissions/manage}
{:name :network-settings
;;TODO accessories
:options {:insets {:top? true}}
:component network/network-settings}
{:name :network-details
:options {:topBar {:title {:text (i18n/label :t/network-details)}}
:insets {:top? true}}
:component network-details/network-details}
{:name :network-info
:options {:topBar {:title {:text (i18n/label :t/network-info)}}
:insets {:top? true}}
:component network-info/network-info}
{:name :rpc-usage-info
:options {:topBar {:title {:text (i18n/label :t/rpc-usage-info)}}
:insets {:top? true}}
@@ -247,10 +231,6 @@
:options {:topBar {:title {:text (i18n/label :t/peers-stats)}}
:insets {:top? true}}
:component peers-stats/peers-stats}
{:name :edit-network
:options {:topBar {:title {:text (i18n/label :t/add-network)}}
:insets {:top? true}}
:component edit-network/edit-network}
{:name :log-level-settings
:options {:topBar {:title {:text (i18n/label :t/log-level-settings)}}
:insets {:top? true}}
+1 -1
View File
@@ -2,7 +2,7 @@
(:require-macros [legacy.status-im.utils.slurp :refer [slurp]])
(:require
[legacy.status-im.fleet.default-fleet :refer (default-fleets)])
(:require [legacy.status-im.utils.test :as utils.test]))
(:require [tests.test-utils :as utils.test]))
;; to generate a js Proxy at js/__STATUS_MOBILE_JS_IDENTITY_PROXY__ that accept any (.xxx) call and
;; return itself
+26
View File
@@ -106,6 +106,32 @@ The convention is `:size-<number>`, e.g size `20` is `:size-20`
- Try to make all other vars private because they should almost never be used
directly.
## Default value when destructuring
Too often callers pass nil values because values can be wrapped in a `when` for example.
In this case, the default value is not applied, because :or macro will use default only when the value is absent.
Instead, use `(or (:value props) some-default-value)` in a `let` expression or as a parameter value.
```clojure
;; bad (unreliable)
(defn- view-internal
[{:keys [auto-focus?
init-value
return-key-type]
:or {auto-focus? false
init-value 0
return-key-type :done}}]
...)
;; good
(defn- view-internal
[{:keys [theme size something] :as props}]
(let [auto-focus? (or (:auto-focus? props) false)
init-value (or (:init-value props) 0)
return-key-type (or (:return-key-type props) :done)]
...))
```
## Component tests
We don't attempt to write component tests verifying how components look on the
@@ -14,28 +14,26 @@
[react-native.reanimated :as reanimated]))
(defn drag-gesture
[x-pos gestures-disabled? set-gestures-disabled disabled? track-width sliding-complete?
[x-pos disabled? track-width sliding-complete?
set-sliding-complete
on-complete reset-fn]
(let [gestures-enabled? (not (or disabled? gestures-disabled?))]
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled gestures-enabled?)
(gesture/min-distance 0)
(gesture/on-update (fn [event]
(let [x-translation (oops/oget event "translationX")
clamped-x (utils/clamp-value x-translation 0 track-width)
reached-end? (>= clamped-x track-width)]
(reanimated/set-shared-value x-pos clamped-x)
(when (and reached-end? (not sliding-complete?))
(set-gestures-disabled true)
(set-sliding-complete true)
(when on-complete (on-complete reset-fn))))))
(gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)]
(when (not reached-end?)
(animations/reset-track-position x-pos))))))))
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled (not disabled?))
(gesture/min-distance 0)
(gesture/on-update (fn [event]
(let [x-translation (oops/oget event "translationX")
clamped-x (utils/clamp-value x-translation 0 track-width)
reached-end? (>= clamped-x track-width)]
(reanimated/set-shared-value x-pos clamped-x)
(when (and reached-end? (not sliding-complete?))
(set-sliding-complete true)
(when on-complete (on-complete reset-fn))))))
(gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)]
(when (not reached-end?)
(animations/reset-track-position x-pos)))))))
(defn view
"Options
@@ -55,14 +53,11 @@
[track-width set-track-width] (rn/use-state nil)
[sliding-complete?
set-sliding-complete] (rn/use-state false)
[gestures-disabled?
set-gestures-disabled] (rn/use-state disabled?)
on-track-layout (rn/use-callback
#(set-track-width (oops/oget % "nativeEvent.layout.width")))
reset-fn (rn/use-callback
(fn []
(set-sliding-complete false)
(set-gestures-disabled false)
(animations/reset-track-position x-pos)))
dimensions (rn/use-callback
(partial utils/get-dimensions
@@ -77,15 +72,13 @@
[dimensions])
custom-color (if (= type :danger) :danger customization-color)
gesture (rn/use-memo #(drag-gesture x-pos
gestures-disabled?
set-gestures-disabled
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn)
[gestures-disabled? sliding-complete? disabled?])]
[sliding-complete? disabled?])]
[gesture/gesture-detector
{:gesture gesture}
[reanimated/view
@@ -20,8 +20,8 @@
[text/text {:size :paragraph-1 :weight :medium :number-of-lines 2} label]]])
(defn channel-actions
[{:keys [style actions]}]
[rn/view {:style (merge {:flex-direction :row :flex 1} style)}
[{:keys [container-style actions]}]
[rn/view {:style (assoc container-style :flex-direction :row)}
(map-indexed
(fn [index action]
^{:key index}
-1
View File
@@ -142,7 +142,6 @@
[color]
{:padding 12
:height 102
:flex 1
:border-radius 16
:background-color (colors/custom-color color 50 10)
:justify-content :space-between})
@@ -65,7 +65,7 @@
{:title "Title"
:type :account
:account-avatar-emoji "🍿"
:networks [{:name :ethereum :short-name "eth"}]
:networks [{:network-name :ethereum :short-name "eth"}]
:description "0x62b...0a5"
:customization-color :purple}]
theme)
@@ -76,7 +76,8 @@
(str description " · " (i18n/label :t/on-device))])
(defn- context-tag-subtitle
[{:keys [context-tag-type community-logo community-name account-name emoji customization-color]}]
[{:keys [context-tag-type community-logo community-name account-name emoji customization-color
full-name profile-picture]}]
(let [tag-type (or context-tag-type :account)]
[rn/view
{:accessibility-label :context-tag-wrapper
@@ -88,7 +89,9 @@
:community-name community-name
:community-logo community-logo
:size 24
:customization-color customization-color}]]))
:customization-color customization-color
:profile-picture profile-picture
:full-name full-name}]]))
(defn- description-subtitle
[{:keys [theme blur? description]}]
@@ -100,7 +103,7 @@
(defn- subtitle
[{:keys [type theme blur? keycard? networks description community-name community-logo
context-tag-type account-name emoji customization-color]}]
context-tag-type account-name emoji customization-color full-name profile-picture]}]
(cond
(= :keypair type)
[keypair-subtitle
@@ -128,7 +131,9 @@
:community-name community-name
:account-name account-name
:emoji emoji
:customization-color customization-color}]
:customization-color customization-color
:profile-picture profile-picture
:full-name full-name}]
(and (not= :label type) description)
[description-subtitle
@@ -187,7 +192,7 @@
on-button-press
on-button-long-press
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
profile-picture keycard? networks label]}]
profile-picture keycard? networks label full-name]}]
[rn/view {:style style/container}
(when (left-image-supported-types type)
[rn/view {:style style/left-container}
@@ -218,7 +223,9 @@
:context-tag-type context-tag-type
:customization-color customization-color
:account-name account-name
:emoji emoji}]]
:emoji emoji
:full-name full-name
:profile-picture profile-picture}]]
[right-icon
{:theme theme
:type type
@@ -2,5 +2,10 @@
(defn root-container
[opacity height]
{:height (or height 252)
:opacity opacity})
{:height (or height 252)
:opacity opacity
:position :absolute
:top 0
:left 0
:right 0
:z-index -1})
+4 -3
View File
@@ -55,16 +55,17 @@
(def ^:private custom-props
"Custom properties that must be removed from properties map passed to InputText."
[:type :blur? :theme :error? :right-icon :left-icon :disabled? :small? :button
[:type :blur? :error? :right-icon :left-icon :disabled? :small? :button
:label :char-limit :on-char-limit-reach :icon-name :multiline? :on-focus :on-blur
:container-style])
(defn- base-input
[{:keys [blur? theme error? right-icon left-icon disabled? small? button
[{:keys [blur? error? right-icon left-icon disabled? small? button
label char-limit multiline? clearable? on-focus on-blur container-style
on-change-text on-char-limit-reach weight default-value]
:as props}]
(let [[status set-status] (rn/use-state :default)
(let [theme (quo.theme/use-theme-value)
[status set-status] (rn/use-state :default)
internal-on-focus (rn/use-callback #(set-status :focus))
internal-on-blur (rn/use-callback #(set-status :default))
[multiple-lines?
@@ -10,7 +10,7 @@
:background-color (colors/theme-colors colors/neutral-10
colors/neutral-80-opa-80
theme)
:height 40
:min-height 40
:padding-horizontal 12
:padding-vertical 9
:margin-top 4})
@@ -22,11 +22,12 @@
(defn- locked-input-internal
[{:keys [label icon container-style theme]} value]
[rn/view {:style container-style}
[text/text
{:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label]
(when label
[text/text
{:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label])
[info-box
{:theme theme
:icon icon
@@ -60,8 +60,8 @@
:padding-horizontal 12
:padding-top 10
:padding-bottom 12
:height (if (= :message size) 245 266)
:width (if (= :message size) 295 335)})
:width (if (= :message size) 295 335)
:flex 1})
(def header-container
{:flex-direction :row
@@ -7,7 +7,6 @@
{:title "Some title"
:description "Some description"
:link "status.im"
:logo "data:image/png,logo-x"
:thumbnail "data:image/png,whatever"})
(h/describe "Links - Link Preview"
@@ -21,17 +20,12 @@
(h/is-truthy (h/query-by-text (:title props)))
(h/is-truthy (h/query-by-text (:description props)))
(h/is-truthy (h/query-by-text (:link props)))
(h/is-truthy (h/query-by-label-text :logo))
(h/is-truthy (h/query-by-label-text :thumbnail)))
(h/test "does not render thumbnail if prop is not present"
(h/render [view/view (dissoc props :thumbnail)])
(h/is-null (h/query-by-label-text :thumbnail)))
(h/test "does not render logo if prop is not present"
(h/render [view/view (dissoc props :logo)])
(h/is-null (h/query-by-label-text :logo)))
(h/test "shows button to enable preview when preview is disabled"
(h/render [view/view
(assoc props
@@ -1,9 +1,14 @@
(ns quo.components.links.link-preview.view
(:require
["react-native-blob-util" :default ReactNativeBlobUtil]
[oops.core :as oops]
[quo.components.buttons.button.view :as button]
[quo.components.links.link-preview.style :as style]
[quo.components.markdown.text :as text]
[react-native.core :as rn]))
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.svg :as svg]
[taoensso.timbre :as log]))
(defn- button-disabled
[disabled-text on-enable]
@@ -51,14 +56,30 @@
thumbnail)
:accessibility-label :thumbnail}])
(defn- get-image-data
[logo set-is-svg on-success]
(-> (.config ReactNativeBlobUtil (clj->js {:trusty platform/ios?}))
(.fetch "GET" logo)
(.then (fn [imgObj]
(set-is-svg (= "image/svg"
(oops/oget imgObj
["respInfo" "headers" "Content-Type"])))
(on-success (oops/oget imgObj "data"))))
(.catch #(log/error "could not fetch favicon " logo))))
(defn- logo-comp
[logo]
[rn/image
{:accessibility-label :logo
:source (if (string? logo)
{:uri logo}
logo)
:style style/logo}])
(let [[image-data set-image-data] (rn/use-state nil)
[is-svg? set-is-svg] (rn/use-state nil)
on-success (fn [data-uri]
(set-image-data data-uri))
_get-image-data (get-image-data logo set-is-svg on-success)]
(if is-svg?
[svg/svg-xml (merge style/logo {:xml image-data})]
[rn/image
{:accessibility-label :logo
:source {:uri (str "data:image/png;base64," image-data)}
:style style/logo}])))
(defn view
[{:keys [title logo description link thumbnail
@@ -21,6 +21,7 @@
:border-radius 12
:border-style :dashed
:align-items :center
:flex-direction :row
:justify-content :center
:align-self :stretch
:padding horizontal-padding
+27 -8
View File
@@ -1,19 +1,31 @@
(ns quo.components.links.url-preview.view
(:require
[clojure.string :as string]
[quo.components.icon :as icon]
[quo.components.links.url-preview.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[react-native.core :as rn]))
[react-native.core :as rn]
[react-native.svg :as svg]))
(def base64-svg-prefix "data:image/svg;base64,")
(defn- logo-comp
[{:keys [logo]}]
[rn/image
{:accessibility-label :logo
:source (if (string? logo)
{:uri logo}
logo)
:style style/logo}])
(if (and (string? logo)
(string/starts-with? logo base64-svg-prefix))
[svg/svg-xml
(merge style/logo
{:xml (-> logo
(string/replace base64-svg-prefix "")
js/atob)})]
[rn/image
{:accessibility-label :logo
:source (if (string? logo)
{:uri logo}
logo)
:style style/logo
:resize-mode :cover}]))
(defn- content
[{:keys [title body]}]
@@ -50,6 +62,10 @@
[rn/view
{:accessibility-label :url-preview-loading
:style (merge (style/loading-container) container-style)}
[icon/icon :i/loading
{:size 12
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:container-style {:margin-right 8}}]
[rn/text
{:size :paragraph-2
:weight :medium
@@ -60,6 +76,9 @@
{:accessibility-label :url-preview
:style (merge (style/container) container-style)}
(when logo
[logo-comp {:logo logo}])
[logo-comp
{:logo (if (map? logo)
(:data-uri logo)
logo)}])
[content {:title title :body body}]
[clear-button {:on-press on-clear}]]))
@@ -32,7 +32,7 @@
[rn/view {:style style/url-preview-separator}])
(defn- item-component
[{:keys [title body loading? logo]} _ _
[{:keys [title body loading? logo url]} _ _
{:keys [width on-clear loading-message container-style]}]
[url-preview/view
{:logo logo
@@ -41,7 +41,8 @@
:loading? loading?
:loading-message loading-message
:on-clear on-clear
:container-style (merge container-style {:width width})}])
:container-style (merge container-style {:width width})
:url url}])
(defn- f-view
[]
@@ -6,71 +6,101 @@
(def ^:private theme :light)
(def ^:private default-props
{:account-props {:name "Account name"
:address "0x1234567890"
:emoji "🍑"
:customization-color "blue"}})
(defn- with-defaults
([] default-props)
([props] (merge default-props props)))
(h/describe "List items: account"
(h/test "default render'"
(h/render-with-theme-provider [account/view] theme)
(h/render-with-theme-provider [account/view (with-defaults)] theme)
(h/is-truthy (h/query-by-label-text :container)))
(h/test "on-press-in changes state to :pressed"
(h/render-with-theme-provider [account/view] theme)
(h/render-with-theme-provider [account/view (with-defaults)] theme)
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/resolve-color :blue :light 5)})))
(h/test "on-press-in changes state to :pressed with blur? enabled"
(h/render-with-theme-provider [account/view {:blur? true}] theme)
(h/render-with-theme-provider [account/view (with-defaults {:blur? true})] theme)
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor colors/white-opa-5})))
(h/test "render with state :active"
(h/render-with-theme-provider [account/view {:state :active}] theme)
(h/render-with-theme-provider [account/view (with-defaults {:state :active})] theme)
(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/resolve-color :blue :light 10)}))
(h/test "render with state :active and blur? enabled"
(h/render-with-theme-provider [account/view
{:blur? true
:state :active}]
(with-defaults
{:blur? true
:state :active})]
theme)
(h/has-style (h/query-by-label-text :container)
{:backgroundColor colors/white-opa-10}))
(h/test "render with state :selected"
(h/render-with-theme-provider [account/view {:state :selected}] theme)
(h/render-with-theme-provider [account/view (with-defaults {:state :selected})] theme)
(h/is-truthy (h/query-by-label-text :check-icon)))
(h/test "calls on-press"
(let [on-press (h/mock-fn)]
(h/render-with-theme-provider [account/view {:on-press on-press}] theme)
(h/render-with-theme-provider [account/view (with-defaults {:on-press on-press})] theme)
(h/fire-event :on-press (h/get-by-label-text :container))
(h/was-called on-press)))
(h/test "renders token props if type :tag"
(h/render-with-theme-provider [account/view {:type :tag}] theme)
(h/render-with-theme-provider [account/view
(with-defaults {:type :tag
:token-props {:symbol "SNT"
:value "1,000"}})]
theme)
(h/is-truthy (h/query-by-label-text :tag-container)))
(h/test "renders keycard icon if title-icon is present"
(h/render-with-theme-provider [account/view {:title-icon :i/placeholder}] theme)
(h/render-with-theme-provider [account/view (with-defaults {:title-icon :i/placeholder})] theme)
(h/is-truthy (h/query-by-label-text :title-icon)))
(h/test "doesn't render keycard icon if title-icon is missing"
(h/render-with-theme-provider [account/view] theme)
(h/render-with-theme-provider [account/view (with-defaults)] theme)
(h/is-falsy (h/query-by-label-text :title-icon)))
(h/test "renders balance container but not arrow icon if type :balance-neutral"
(h/render-with-theme-provider [account/view {:type :balance-neutral}] theme)
(h/render-with-theme-provider [account/view
(with-defaults {:type :balance-neutral
:balance-props {:fiat-value "€0.00"
:percentage-change "0.0"
:fiat-change "€0.00"}})]
theme)
(h/is-truthy (h/query-by-label-text :balance-container))
(h/is-falsy (h/query-by-label-text :arrow-icon)))
(h/test "renders balance container and negative arrow icon if type :balance-negative"
(h/render-with-theme-provider [account/view {:type :balance-negative}] theme)
(h/render-with-theme-provider [account/view
(with-defaults {:type :balance-negative
:balance-props {:fiat-value "€0.00"
:percentage-change "0.0"
:fiat-change "€0.00"}})]
theme)
(h/is-truthy (h/query-by-label-text :balance-container))
(h/is-truthy (h/query-by-label-text :icon-negative))
(h/is-falsy (h/query-by-label-text :icon-positive)))
(h/test "renders balance container and positive arrow icon if type :balance-positive"
(h/render-with-theme-provider [account/view {:type :balance-positive}] theme)
(h/render-with-theme-provider [account/view
(with-defaults {:type :balance-positive
:balance-props {:fiat-value "€0.00"
:percentage-change "0.0"
:fiat-change "€0.00"}})]
theme)
(h/is-truthy (h/query-by-label-text :balance-container))
(h/is-falsy (h/query-by-label-text :icon-negative))
(h/is-truthy (h/query-by-label-text :icon-positive)))
@@ -78,8 +108,9 @@
(h/test "renders options button if type :action"
(let [on-options-press (h/mock-fn)]
(h/render-with-theme-provider [account/view
{:type :action
:on-options-press on-options-press}]
(with-defaults
{:type :action
:on-options-press on-options-press})]
theme)
(h/is-truthy (h/query-by-label-text :options-button))
(h/fire-event :on-press (h/get-by-label-text :options-button))
@@ -0,0 +1,50 @@
(ns quo.components.list-items.account.schema)
(def ^:private ?balance
[:map
[:balance-props
[:map
[:fiat-value :string]
[:percentage-change :string]
[:fiat-change :string]]]])
(def ^:private ?tag
[:map
[:token-props
[:map
[:symbol :string]
[:value :string]]]])
(def ^:private ?action
[:map
[:on-options-press {:optional true} [:maybe fn?]]])
(def ^:private ?base
[:map
[:type {:optional true}
[:enum :default :tag :action :balance-neutral :balance-negative :balance-positive]]
[:state {:optional true} [:enum :default :selected :active]]
[:blur? {:optional true} [:maybe :boolean]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:on-press {:optional true} [:maybe fn?]]
[:theme :schema.common/theme]
[:title-icon {:optional true} [:maybe :keyword]]
[:account-props
[:map
[:name :string]
[:address :string]
[:emoji :string]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]])
(def ?schema
[:=>
[:cat
[:multi {:dispatch :type}
[:balance-neutral [:merge ?base ?balance]]
[:balance-negative [:merge ?base ?balance]]
[:balance-positive [:merge ?base ?balance]]
[:tag [:merge ?base ?tag]]
[:action [:merge ?base ?action]]
[:default ?base]
[:malli.core/default ?base]]]
:any])
@@ -2,13 +2,15 @@
(:require
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.icon :as icon]
[quo.components.list-items.account.schema :as component-schema]
[quo.components.list-items.account.style :as style]
[quo.components.markdown.text :as text]
[quo.components.wallet.address-text.view :as address-text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[schema.core :as schema]))
(defn- account-view
[{:keys [account-props title-icon blur? theme]}]
@@ -130,4 +132,6 @@
(and (= type :default) (= state :selected))
[check-icon props])]])))
(def view (quo.theme/with-theme internal-view))
(def view
(quo.theme/with-theme
(schema/instrument #'internal-view component-schema/?schema)))
@@ -13,9 +13,9 @@
(h/describe "List items: account list card"
(h/test "Test icon renders for ':action :icon'"
(h/render [account-list-card/view
{:account-props account-props
:network :ethereum
:state :default
:action :icon}])
(h/render-with-theme-provider [account-list-card/view
{:account-props account-props
:network :ethereum
:action :icon
:on-options-press (fn [])}])
(h/is-truthy (h/get-by-label-text :icon))))
@@ -0,0 +1,30 @@
(ns quo.components.list-items.account-list-card.schema)
(def ^:private ?base
[:map
[:action {:optional true} [:enum :icon :none]]
[:blur? {:optional true} [:maybe :boolean]]
[:on-press {:optional true} [:maybe fn?]]
[:theme :schema.common/theme]
[:account-props
[:map {:closed true}
[:type [:enum :default :watch-only]]
[:name :string]
[:address :string]
[:emoji :string]
[:size {:optional true} [:enum 80 :size-64 48 32 28 24 20 16]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]
[:networks {:optional true} [:* [:map [:network-name :keyword] [:short-name :string]]]]])
(def ^:private ?on-option-press
[:map
[:on-options-press [:maybe fn?]]])
(def ?schema
[:=>
[:cat
[:multi {:dispatch :action}
[:icon [:merge ?base ?on-option-press]]
[:none ?base]
[:malli.core/default ?base]]]
:any])
@@ -2,13 +2,15 @@
(:require
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.icon :as icon]
[quo.components.list-items.account-list-card.schema :as component-schema]
[quo.components.list-items.account-list-card.style :as style]
[quo.components.markdown.text :as text]
[quo.components.wallet.address-text.view :as address-text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[schema.core :as schema]))
(defn- internal-view
[]
@@ -39,4 +41,6 @@
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))
:accessibility-label :icon}]])])))
(def view (quo.theme/with-theme internal-view))
(def view
(quo.theme/with-theme
(schema/instrument #'internal-view component-schema/?schema)))
@@ -4,32 +4,36 @@
[quo.foundations.colors :as colors]
[test-helpers.component :as h]))
(defn- with-defaults
([] (with-defaults {}))
([props] (merge {:address "0x0ah...78b"} props)))
(h/describe "List items: address"
(h/test "default render"
(h/render [address/view])
(h/render-with-theme-provider [address/view (with-defaults)])
(h/is-truthy (h/query-by-label-text :container)))
(h/test "on-press-in changes state to :pressed"
(h/render [address/view])
(h/render-with-theme-provider [address/view (with-defaults)])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 5)})))
(h/test "on-press-in changes state to :pressed with blur? enabled"
(h/render [address/view {:blur? true}])
(h/render-with-theme-provider [address/view (with-defaults {:blur? true})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor colors/white-opa-5})))
(h/test "on-press-out changes state to :active"
(h/render [address/view {:active-state? true}])
(h/render-with-theme-provider [address/view (with-defaults {:active-state? true})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 10)})))
(h/test "on-press-out changes state to :active with blur? enabled"
(h/render [address/view {:active-state? true :blur? true}])
(h/render-with-theme-provider [address/view (with-defaults {:active-state? true :blur? true})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
@@ -37,6 +41,6 @@
(h/test "on-press event is called"
(let [on-press (h/mock-fn)]
(h/render [address/view {:on-press on-press}])
(h/render-with-theme-provider [address/view (with-defaults {:on-press on-press})])
(h/fire-event :on-press (h/get-by-label-text :container))
(h/was-called on-press))))
@@ -0,0 +1,14 @@
(ns quo.components.list-items.address.schema)
(def ?schema
[:=>
[:cat
[:map
[:address :string]
[:networks {:optional true} [:* [:map [:network-name :keyword] [:short-name :string]]]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:on-press {:optional true} [:maybe fn?]]
[:blur? {:optional true} [:maybe :boolean]]
[:theme :schema.common/theme]
[:active-state? {:optional true} [:maybe :boolean]]]]
:any])
@@ -1,12 +1,14 @@
(ns quo.components.list-items.address.view
(:require
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
(quo.components.list-items.address.schema :as component-schema)
[quo.components.list-items.address.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[schema.core :as schema]
[utils.address :as address]))
(defn- left-container
@@ -64,4 +66,7 @@
:address address
:blur? blur?}]]))))
(def view (quo.theme/with-theme internal-view))
(def view
(quo.theme/with-theme
(schema/instrument #'internal-view component-schema/?schema)))
@@ -4,6 +4,10 @@
[quo.foundations.colors :as colors]
[test-helpers.component :as h]))
(defn- with-defaults
([] (with-defaults {}))
([props] (merge {:contact-props {:full-name "Thomas Anderson"}} props)))
(def account
{:name "New House"
:address "0x21a...49e"
@@ -12,25 +16,33 @@
(h/describe "List items: saved contact address"
(h/test "default render"
(h/render-with-theme-provider [saved-contact-address/view])
(h/render-with-theme-provider [saved-contact-address/view (with-defaults)])
(h/is-truthy (h/query-by-label-text :container)))
(h/test "renders account detail when passing one account"
(h/render-with-theme-provider [saved-contact-address/view {:accounts (repeat 1 account)}])
(h/render-with-theme-provider [saved-contact-address/view
(with-defaults
{:accounts (repeat 1 account)})])
(h/is-truthy (h/query-by-label-text :account-container)))
(h/test "renders account count when passing multiple accounts"
(h/render-with-theme-provider [saved-contact-address/view {:accounts (repeat 2 account)}])
(h/render-with-theme-provider [saved-contact-address/view
(with-defaults
{:accounts (repeat 2 account)})])
(h/is-truthy (h/query-by-label-text :accounts-count)))
(h/test "on-press-in changes state to :pressed"
(h/render-with-theme-provider [saved-contact-address/view {:accounts (repeat 1 account)}])
(h/render-with-theme-provider [saved-contact-address/view
(with-defaults
{:accounts (repeat 1 account)})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 5)})))
(h/test "on-press-out changes state to :active if active-state? is true (default value)"
(h/render-with-theme-provider [saved-contact-address/view {:accounts (repeat 1 account)}])
(h/render-with-theme-provider [saved-contact-address/view
(with-defaults
{:accounts (repeat 1 account)})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
@@ -38,8 +50,9 @@
(h/test "on-press-out changes state to :default if active-state? is false"
(h/render-with-theme-provider [saved-contact-address/view
{:accounts (repeat 1 account)
:active-state? false}])
(with-defaults
{:accounts (repeat 1 account)
:active-state? false})])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
@@ -47,9 +60,9 @@
(h/test "on-press calls on-press"
(let [on-press (h/mock-fn)]
(h/render-with-theme-provider
[saved-contact-address/view
{:on-press on-press
:accounts (repeat 1 account)}])
(h/render-with-theme-provider [saved-contact-address/view
(with-defaults
{:on-press on-press
:accounts (repeat 1 account)})])
(h/fire-event :on-press (h/get-by-label-text :container))
(h/was-called on-press))))
@@ -0,0 +1,29 @@
(ns quo.components.list-items.saved-contact-address.schema)
(def ^:private ?contact
[:map
[:full-name :string]
[:profile-picture {:optional true} [:maybe [:or :schema.common/image-source :string]]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]])
(def ^:private ?account
[:map
[:name :string]
[:address :string]
[:emoji {:optional true} :string]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]])
(def ^:private ?accounts
[:+ ?account])
(def ?schema
[:=>
[:cat
[:map
[:contact-props ?contact]
[:accounts {:optional true} ?accounts]
[:on-press {:optional true} [:maybe fn?]]
[:theme :schema.common/theme]
[:active-state? {:optional true} [:maybe :boolean]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]
:any])
@@ -3,12 +3,14 @@
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.icon :as icon]
[quo.components.list-items.saved-contact-address.schema :as component-schema]
[quo.components.list-items.saved-contact-address.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[schema.core :as schema]
[utils.address :as address]
[utils.i18n :as i18n]))
@@ -92,4 +94,6 @@
colors/neutral-40
theme)}])]))))
(def view (quo.theme/with-theme internal-view))
(def view
(quo.theme/with-theme
(schema/instrument #'internal-view component-schema/?schema)))
@@ -8,40 +8,36 @@
{:token :snt
:state :default
:label "Status"
:networks [(resources/get-network :ethereum)]
:networks [{:source (resources/get-network :ethereum)}]
:token-value "100.00 SNT"
:fiat-value "€0.00"})
(h/describe "List items: Token network"
(h/test "default state"
(h/render [token-network/view (dissoc props :state)])
(h/render-with-theme-provider [token-network/view (dissoc props :state)])
(h/is-truthy (h/get-by-text "Status")))
(h/test "default state explicit"
(h/render [token-network/view props])
(h/render-with-theme-provider [token-network/view props])
(h/is-truthy (h/get-by-text "Status")))
(h/test "Pressed state"
(h/render [token-network/view props])
(h/render-with-theme-provider [token-network/view props])
(h/fire-event :on-press-in (h/get-by-label-text :token-network))
(h/wait-for #(h/has-style (h/query-by-label-text :token-network)
{:backgroundColor (colors/resolve-color :blue :light 5)})))
(h/test "Active state"
(h/render [token-network/view (assoc props :state :active)])
(h/render-with-theme-provider [token-network/view (assoc props :state :active)])
(h/has-style (h/query-by-label-text :token-network)
{:backgroundColor (colors/resolve-color :blue :light 10)}))
(h/test "Selected state"
(h/render [token-network/view (assoc props :state :selected)])
(h/render-with-theme-provider [token-network/view (assoc props :state :selected)])
(h/is-truthy (h/query-by-label-text :check-icon)))
(h/test "Call on-press"
(let [on-press (h/mock-fn)]
(h/render [token-network/view (assoc props :on-press on-press)])
(h/render-with-theme-provider [token-network/view (assoc props :on-press on-press)])
(h/fire-event :on-press (h/get-by-label-text :token-network))
(h/was-called on-press)))
(h/test "Empty props"
(h/render [token-network/view {}])
(h/is-truthy (h/get-by-label-text :token-network))))
(h/was-called on-press))))
@@ -0,0 +1,16 @@
(ns quo.components.list-items.token-network.schema)
(def ?schema
[:=>
[:cat
[:map
[:token :keyword]
[:label :string]
[:token-value :string]
[:fiat-value :string]
[:networks [:* [:map [:source :schema.common/image-source]]]]
[:on-press {:optional true} [:maybe fn?]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:state {:optional true} [:enum :default :active :selected]]
[:theme :schema.common/theme]]]
:any])
@@ -2,12 +2,14 @@
(:require
[quo.components.icon :as icon]
[quo.components.list-items.preview-list.view :as preview-list]
[quo.components.list-items.token-network.schema :as component-schema]
[quo.components.list-items.token-network.style :as style]
[quo.components.markdown.text :as text]
[quo.components.utilities.token.view :as token]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[schema.core :as schema]))
(defn- info
[{:keys [token label networks]}]
@@ -67,4 +69,6 @@
[info props]
[values props]]))))
(def view (quo.theme/with-theme view-internal))
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))
@@ -5,29 +5,29 @@
(h/describe "List Items: Token Value"
(h/test "Token label renders"
(h/render [token-value/view
{:token :snt
:token-name "Status"
:state :default
:status :empty
:customization-color :blue
:metrics? true
:values {:crypto-value "0.00"
:fiat-value "€0.00"
:percentage-change "0.00"
:fiat-change "€0.00"}}])
(h/render-with-theme-provider [token-value/view
{:token :snt
:token-name "Status"
:state :default
:status :empty
:customization-color :blue
:metrics? true
:values {:crypto-value "0.00"
:fiat-value "€0.00"
:percentage-change "0.00"
:fiat-change "€0.00"}}])
(h/is-truthy (h/get-by-text "Status")))
(h/test "Status change"
(h/render [token-value/view
{:token :snt
:token-name "Status"
:state :default
:status :positive
:customization-color :blue
:metrics? true
:values {:crypto-value "0.00"
:fiat-value "€0.00"
:percentage-change "0.00"
:fiat-change "€0.00"}}])
(h/render-with-theme-provider [token-value/view
{:token :snt
:token-name "Status"
:state :default
:status :positive
:customization-color :blue
:metrics? true
:values {:crypto-value "0.00"
:fiat-value "€0.00"
:percentage-change "0.00"
:fiat-change "€0.00"}}])
(h/is-truthy (h/get-by-label-text :arrow-icon))))
@@ -0,0 +1,23 @@
(ns quo.components.list-items.token-value.schema)
(def ^:private ?values
[:map
[:crypto-value :string]
[:fiat-value :string]
[:percentage-change {:optional true} :string]
[:fiat-change {:optional true} :string]])
(def ?schema
[:=>
[:cat
[:map
[:token [:or keyword? string?]]
[:token-name :string]
[:status [:enum :empty :positive :negative]]
[:values ?values]
[:on-press {:optional true} [:maybe fn?]]
[:on-long-press {:optional true} [:maybe fn?]]
[:theme :schema.common/theme]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:metrics? {:optional true} [:maybe :boolean]]]]
:any])
@@ -2,13 +2,15 @@
(:require
[clojure.string :as string]
[quo.components.icon :as icon]
[quo.components.list-items.token-value.schema :as component-schema]
[quo.components.list-items.token-value.style :as style]
[quo.components.markdown.text :as text]
[quo.components.utilities.token.view :as token]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[schema.core :as schema]))
(defn- internal-view
[]
@@ -65,4 +67,6 @@
[icon/icon (if (= status :positive) :i/positive :i/negative)
(style/arrow-icon status theme)]])])]]))))
(def view (quo.theme/with-theme internal-view))
(def view
(quo.theme/with-theme
(schema/instrument #'internal-view component-schema/?schema)))
@@ -35,7 +35,7 @@
:on-press on-press
:background (if behind-overlay?
:blur
(button-properties/backgrounds background))
(when (button-properties/backgrounds background) background))
:accessibility-label accessibility-label}
icon-name])]
children))
@@ -1,9 +1,9 @@
(ns quo.components.profile.collectible.view
(:require
[clojure.string :as string]
[quo.components.markdown.text :as text]
[quo.components.profile.collectible.style :as style]
[react-native.core :as rn]
[react-native.svg :as svg]))
[react-native.core :as rn]))
(defn remaining-tiles
[amount]
@@ -19,11 +19,28 @@
(let [svg? (and (map? resource) (:svg? resource))
image-style (style/tile-style-by-size size)]
[rn/view {:style style}
(if svg?
(cond
svg?
[rn/view
{:style {:border-radius (:border-radius image-style)
:overflow :hidden}}
[svg/svg-uri (assoc image-style :uri (:uri resource))]]
{:style (assoc image-style
:border-radius (:border-radius image-style)
:overflow :hidden
:justify-content :center
:align-items :center
:background-color :lightblue)}
[text/text "SVG Content"]]
(or (string/blank? resource) (string/blank? (:uri resource)))
[rn/view
{:style (assoc image-style
:border-radius (:border-radius image-style)
:overflow :hidden
:justify-content :center
:align-items :center
:background-color :lightgray)}
[text/text "Missing image"]]
:else
;; NOTE: using react-native-fast-image here causes a crash on devices when used inside a
;; large flatlist. The library seems to have issues with memory consumption when used with
;; large images/GIFs.
@@ -16,9 +16,9 @@
(reagent/flush))
(defn- reorder-category-internal
[{:keys [label data blur? theme]}]
[{:keys [label data blur? theme container-style]}]
(reagent/with-let [atom-data (reagent/atom data)]
[rn/view {:style style/container}
[rn/view {:style (merge (style/container label) container-style)}
[text/text
{:weight :medium
:size :paragraph-2
@@ -23,7 +23,7 @@
(def ?profile
[:map
[:type [:= :profile]]
[:profile-picture :schema.common/image-source]])
[:profile-picture [:maybe :schema.quo/profile-picture-source]]])
(def ?wallet
[:map
@@ -150,8 +150,7 @@
profile-picture emoji on-share-press address]
:as props}]
[:<>
[rn/view {:style style/gradient-bg}
[gradient-cover/view {:customization-color customization-color :height 463}]]
[gradient-cover/view {:customization-color customization-color :height 463}]
[rn/view {:style style/content-container}
[rn/view {:style style/share-qr-container}
[rn/view {:style style/share-qr-inner-container}
@@ -1,5 +1,6 @@
(ns quo.components.wallet.account-permissions.view
(:require [quo.components.avatars.account-avatar.view :as account-avatar]
(:require [clojure.string :as string]
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.dividers.divider-line.view :as divider-line]
[quo.components.icon :as icons]
[quo.components.markdown.text :as text]
@@ -28,17 +29,24 @@
(i18n/label :t/no-relevant-tokens)]
(let [token-length (dec (count tokens))]
(map-indexed (fn [idx {:keys [type token amount collectible-name collectible-img-src]}]
^{:key idx}
[required-tokens/view
{:container-style style/token-and-text
:type type
:amount amount
:token token
:collectible-img-src collectible-img-src
:collectible-name collectible-name
:divider? (not= token-length idx)}])
tokens)))]]))
(map-indexed
(fn [idx
{:keys [type token amount collectible-name collectible-img-src
token-img-src]
collectible-symbol :symbol}]
^{:key idx}
[required-tokens/view
{:container-style style/token-and-text
:type type
:amount amount
:token token
:token-img-src token-img-src
:collectible-img-src collectible-img-src
:collectible-name (if (string/blank? collectible-name)
collectible-symbol
collectible-name)
:divider? (not= token-length idx)}])
tokens)))]]))
(defn- view-internal
[{:keys
@@ -10,5 +10,5 @@
[:format {:optional true} [:enum :short :long]]
[:theme :schema.common/theme]
[:networks {:optional true}
[:maybe [:sequential [:map [:name :keyword] [:short-name :string]]]]]]]]
[:maybe [:sequential [:map [:network-name :keyword] [:short-name :string]]]]]]]]
:any])
@@ -20,7 +20,8 @@
(let [network-text-xf (map #(colored-network-text theme %))
address-text [text/text
{:size :paragraph-2
;; TODO: monospace font https://github.com/status-im/status-mobile/issues/17009
;; TODO: monospace font
;; https://github.com/status-im/status-mobile/issues/17009
:weight :monospace
:style (style/address-text format blur? theme)}
(if (= format :short)
@@ -12,9 +12,8 @@
:type :default
:name "Trip to Vegas"
:address "0x0ah...71a"}
:networks [{:name :ethereum :short-name "eth"}
{:name :optimism :short-name "opt"}]
:state :default
:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}]
:action :none}])
(def default-details
@@ -55,7 +54,7 @@
:action :selector
:details other-details}]
theme)
(h/is-truthy (h/get-by-label-text :radio-on)))
(h/is-truthy (h/get-by-label-text :radio-off)))
(h/test "Options action renders"
(h/render-with-theme-provider [keypair/view
+7 -1
View File
@@ -1,6 +1,7 @@
(ns quo.components.wallet.keypair.style
(:require
[quo.foundations.colors :as colors]))
[quo.foundations.colors :as colors]
[react-native.platform :as platform]))
(defn container
[{:keys [blur? customization-color theme selected?]}]
@@ -34,3 +35,8 @@
{:color (if blur?
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
(defn dot
[blur? theme]
(merge (subtitle blur? theme)
{:bottom (if platform/ios? 2 -2)}))
+13 -9
View File
@@ -11,7 +11,6 @@
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[utils.i18n :as i18n]))
@@ -60,7 +59,7 @@
:accessibility-label :options-button}]])]))
(defn details-view
[{:keys [details stored blur? theme]}]
[{:keys [details stored type blur? theme]}]
(let [{:keys [address]} details]
[rn/view
{:style {:flex-direction :row
@@ -70,10 +69,11 @@
{:size :paragraph-2
:style (style/subtitle blur? theme)}
address]
[text/text
{:size :paragraph-2
:style (merge (style/subtitle blur? theme) {:bottom (if platform/ios? 2 -2)})}
" ∙ "]
(when (= type :default-keypair)
[text/text
{:size :paragraph-2
:style (style/dot blur? theme)}
" ∙ "])
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}
@@ -86,9 +86,13 @@
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])]))
(defn- acc-list-card
[item & _rest]
[account-list-card/view item])
(defn- view-internal
[]
(let [selected? (reagent/atom true)]
[{:keys [default-selected?]}]
(let [selected? (reagent/atom default-selected?)]
(fn [{:keys [accounts action container-style] :as props}]
[rn/pressable
{:style (merge (style/container (merge props {:selected? @selected?})) container-style)
@@ -102,7 +106,7 @@
[details-view props]]]
[rn/flat-list
{:data accounts
:render-fn account-list-card/view
:render-fn acc-list-card
:separator [rn/view {:style {:height 8}}]
:style {:padding-horizontal 8}}]])))
@@ -30,7 +30,7 @@
:style {:margin-left 4}}
(case type
:token (str amount " " token)
:collectible collectible-name
:collectible (str amount " " collectible-name)
nil)]
(when divider?
[rn/view
@@ -30,8 +30,8 @@
(defn networks
[values theme]
(let [{:keys [ethereum optimism arbitrum]} values
show-optimism? (pos? optimism)
show-arbitrum? (pos? arbitrum)]
show-optimism? (and optimism (pos? (:amount optimism)))
show-arbitrum? (and arbitrum (pos? (:amount arbitrum)))]
[rn/view
{:style style/networks-container
:accessibility-label :networks}
+1
View File
@@ -35,6 +35,7 @@
(def ^:private networks
{:arbitrum (js/require "../resources/images/networks/Arbitrum.png")
:ethereum (js/require "../resources/images/networks/Ethereum.png")
:mainnet (js/require "../resources/images/networks/Ethereum.png")
:gnosis (js/require "../resources/images/networks/Gnosis.png")
:hermez (js/require "../resources/images/networks/Hermez.png")
:optimism (js/require "../resources/images/networks/Optimism.png")
+5 -5
View File
@@ -39,13 +39,13 @@
[message]
(let [cause (if platform/android?
(condp = message
android-not-enrolled-error-message ::not-enrolled
android-not-available-error-message ::not-available
::unknown)
android-not-enrolled-error-message :biometrics/not-enrolled-error
android-not-available-error-message :biometrics/not-available-error
:biometrics/unknown-error)
(condp #(string/includes? %2 %1) message
ios-not-enrolled-error-message ::not-enrolled
::unknown))]
ios-not-enrolled-error-message :biometrics/not-enrolled-error
:biometrics/unknown-error))]
(ex-info "Failed to authenticate with biometrics"
{:orig-error-message message}
cause)))
+21 -5
View File
@@ -3,6 +3,7 @@
["react" :as react]
["react-native" :as react-native]
[oops.core :as oops]
[promesa.core :as p]
[react-native.flat-list :as flat-list]
[react-native.platform :as platform]
[react-native.section-list :as section-list]
@@ -24,12 +25,23 @@
(defn image
[{:keys [source] :as props}]
[image-native
(if (string? source)
(assoc props :source {:uri source})
props)])
(let [props (cond-> props
platform/ios?
(dissoc :resize-method)
(and (:style props) platform/ios?)
(update :style dissoc :resize-method))]
[image-native
(if (string? source)
(assoc props :source {:uri source})
props)]))
(defn image-get-size [uri callback] (.getSize ^js (.-Image ^js react-native) uri callback))
(defn image-get-size
[uri]
(p/create (fn [res rej]
(.getSize ^js (.-Image ^js react-native)
uri
(fn [width height] (res [width height]))
rej))))
(def text (reagent/adapt-react-class (.-Text ^js react-native)))
(def text-input (reagent/adapt-react-class (.-TextInput ^js react-native)))
@@ -212,3 +224,7 @@
(defn open-url [link] (.openURL ^js linking link))
(def set-status-bar-style react-native/StatusBar.setBarStyle)
(defn sharing
[content]
(.share (.-Share ^js react-native) (clj->js content)))
+2 -4
View File
@@ -3,7 +3,5 @@
["react-native-image-resizer" :default image-resizer]))
(defn resize
[path max-width max-height quality on-resize on-error]
(-> (.createResizedImage image-resizer path max-width max-height "JPEG" quality 0 nil false)
(.then on-resize)
(.catch on-error)))
[{:keys [path max-width max-height quality]}]
(.createResizedImage image-resizer path max-width max-height "JPEG" quality 0 nil false))
+6 -1
View File
@@ -29,10 +29,15 @@
[:on-success [:or fn? [:cat keyword? [:* :any]]]]
[:on-error [:or fn? [:cat keyword? [:* :any]]]]]])
(def ^:private ?exception
[:fn {:error/message "schema.common/exception should be of type ExceptionInfo"}
(fn [v] (instance? ExceptionInfo v))])
(defn register-schemas
[]
(registry/register ::theme ?theme)
(registry/register ::customization-color ?customization-color)
(registry/register ::public-key ?public-key)
(registry/register ::image-source ?image-source)
(registry/register ::rpc-call ?rpc-call))
(registry/register ::rpc-call ?rpc-call)
(registry/register ::exception ?exception))
@@ -0,0 +1,27 @@
(ns status-im.common.alert-banner.events
(:require [re-frame.core :as re-frame]))
(defn add-alert-banner
[{:keys [db]} [banner]]
(let [current-banners-count (count (get db :alert-banners))
db (assoc-in db [:alert-banners (:type banner)] banner)]
(cond-> {:db db}
(zero? current-banners-count)
(assoc :show-alert-banner nil))))
(defn remove-alert-banner
[{:keys [db]} [banner-type]]
(let [db (update-in db [:alert-banners] dissoc banner-type)
new-count (count (get db :alert-banners))]
(cond-> {:db db}
(zero? new-count)
(assoc :hide-alert-banner nil))))
(defn remove-all-alert-banners
[{:keys [db]}]
{:db (dissoc db :alert-banners)
:hide-alert-banner nil})
(re-frame/reg-event-fx :alert-banners/add add-alert-banner)
(re-frame/reg-event-fx :alert-banners/remove remove-alert-banner)
(re-frame/reg-event-fx :alert-banners/remove-all remove-all-alert-banners)
@@ -0,0 +1,42 @@
(ns status-im.common.alert-banner.events-test
(:require
[cljs.test :refer [deftest is testing]]
matcher-combinators.test
[status-im.common.alert-banner.events :as events]))
(deftest add-alert-banner
(testing "Alert banner is added"
(is (match? {:db {:alert-banners
{:alert {:text "Alert"
:type :alert}}}
:show-alert-banner nil}
(events/add-alert-banner {:db {}}
[{:text "Alert"
:type :alert}])))))
(deftest remove-alert-banner
(testing "Alert banner is removed"
(is (match? {:db {}
:hide-alert-banner nil}
(events/remove-alert-banner {:db {:alert-banners
{:alert {:text "Alert"
:type :alert}}}}
[:alert]))))
(testing "Alert banner is not removed"
(is (match? {:db {:alert-banners
{:alert {:text "Alert"
:type :alert}}}}
(events/remove-alert-banner {:db {:alert-banners
{:alert {:text "Alert"
:type :alert}}}}
[:error])))))
(deftest remove-all-alert-banners
(testing "All Alert banners are removed"
(is (match? {:db {}
:hide-alert-banner nil}
(events/remove-all-alert-banners {:db {:alert-banners
{:alert {:text "Alert"
:type :alert}
:error {:text "Error"
:type :error}}}})))))
@@ -0,0 +1,20 @@
(ns status-im.common.alert-banner.style)
(def border-radius 20)
(defn container
[background-color]
{:background-color background-color})
(def second-banner-wrapper
{:margin-top (- border-radius)
:overflow :hidden
:border-top-left-radius border-radius
:border-top-right-radius border-radius})
(defn hole-view
[background-color]
{:padding-top 11
:align-items :center
:height 60
:background-color background-color})
@@ -0,0 +1,68 @@
(ns status-im.common.alert-banner.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.safe-area :as safe-area]
[status-im.common.alert-banner.style :as style]
[status-im.constants :as constants]
[utils.re-frame :as rf]))
(defn get-colors-map
[theme]
{:alert
{:background-color (colors/resolve-color :warning theme 20)
:text-color (colors/resolve-color :warning theme)}
:error
{:background-color (colors/resolve-color :danger theme 20)
:text-color (colors/resolve-color :danger theme)}})
(defn- banner
[{:keys [text type second-banner? colors-map]}]
[rn/view (when second-banner? {:style style/second-banner-wrapper})
[hole-view/hole-view
{:style (style/hole-view (get-in colors-map [type :background-color]))
:holes (if second-banner?
[]
[{:x 0
:y constants/alert-banner-height
:width (:width (rn/get-window))
:height constants/alert-banner-height
:borderRadius style/border-radius}])}
[quo/text
{:size :paragraph-2
:weight :medium
:style {:color (get-in colors-map [type :text-color])}}
text]]])
(defn view
[]
(let [banners (rf/sub [:alert-banners])
theme (quo.theme/use-theme-value)
banners-count (count banners)
alert-banner (:alert banners)
error-banner (:error banners)
safe-area-top (safe-area/get-top)
colors-map (get-colors-map theme)]
[hole-view/hole-view
{:style {:background-color colors/neutral-100}
:holes [{:x 0
:y (+ safe-area-top (* constants/alert-banner-height banners-count))
:width (:width (rn/get-window))
:height constants/alert-banner-height
:borderRadius style/border-radius}]}
[rn/view
{:style {:height safe-area-top
:background-color (get-in colors-map
[(if error-banner :error :alert) :background-color])}}]
(when error-banner
[banner
(assoc error-banner
:colors-map colors-map
:second-banner? false)])
(when alert-banner
[banner
(assoc alert-banner
:colors-map colors-map
:second-banner? (= 2 banners-count))])]))
@@ -0,0 +1,72 @@
(ns status-im.common.biometric.effects
(:require
[react-native.biometrics :as biometrics]
[status-im.common.biometric.utils :as utils]
[status-im.common.keychain.events :as keychain]
[status-im.constants :as constant]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(rf/reg-fx
:effects.biometric/get-supported-type
(fn []
;;NOTE: if we can't save user password, we can't use biometric
(keychain/can-save-user-password?
(fn [can-save?]
(when (and can-save? (not utils/android-device-blacklisted?))
(-> (biometrics/get-supported-type)
(.then (fn [type]
(rf/dispatch [:biometric/set-supported-type type])))))))))
(rf/reg-fx
:effects.biometric/authenticate
(fn [{:keys [prompt-message on-success on-fail on-cancel on-done]
:or {on-done identity
on-success identity
on-cancel identity
on-fail identity}}]
(-> (biometrics/authenticate
{:prompt-message (or prompt-message (i18n/label :t/biometric-auth-reason-login))
:fallback-prompt-message (i18n/label
:t/biometric-auth-login-ios-fallback-label)
:cancel-button-text (i18n/label :t/cancel)})
(.then (fn [success?]
(on-done)
(if success?
(on-success)
(on-cancel))))
(.catch (fn [err]
(on-done)
(on-fail err))))))
(rf/reg-fx
:effects.biometric/check-if-available
(fn [{:keys [key-uid on-success on-fail]
:or {on-success identity
on-fail identity}}]
(keychain/can-save-user-password?
(fn [can-save?]
(if-not can-save?
(on-fail (ex-info "cannot-save-user-password"
{:effect :effects.biometric/check-if-available}))
(-> (biometrics/get-available)
(.then (fn [available?]
(when-not available?
(throw (js/Error. "biometric-not-available")))))
(.then #(keychain/get-auth-method! key-uid))
(.then (fn [auth-method]
(if (= auth-method constant/auth-method-biometric)
(on-success auth-method)
(throw (js/Error. "biometric-not-enabled")))))
(.catch (fn [err]
(let [message (.-message err)]
(on-fail (ex-info message
{:err err
:effect :effects.biometric/check-if-available}))
(when-not (or (= message "biometric-not-available")
(= message "biometric-not-enabled"))
(log/error "Failed to check if biometrics is available"
{:error err
:key-uid key-uid
:effect :effects.biometric/check-biometric})))))))))))
+44 -102
View File
@@ -1,120 +1,62 @@
(ns status-im.common.biometric.events
(:require
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[react-native.biometrics :as biometrics]
[react-native.platform :as platform]
[status-im.common.keychain.events :as keychain]
status-im.common.biometric.effects
[status-im.constants :as constants]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def android-device-blacklisted?
(and platform/android? (= (:brand (native-module/get-device-model-info)) "bannedbrand")))
(defn set-supported-type
[{:keys [db]} [supported-type]]
{:db (assoc-in db [:biometrics :supported-type] supported-type)})
(defn get-label-by-type
[biometric-type]
(condp = biometric-type
constants/biometrics-type-android (i18n/label :t/biometric-fingerprint)
constants/biometrics-type-face-id (i18n/label :t/biometric-faceid)
(i18n/label :t/biometric-touchid)))
(rf/reg-event-fx :biometric/set-supported-type set-supported-type)
(defn get-icon-by-type
[biometric-type]
(condp = biometric-type
constants/biometrics-type-face-id :i/face-id
:i/touch-id))
(re-frame/reg-fx
:biometric/get-supported-biometric-type
(fn []
;;NOTE: if we can't save user password, we can't use biometric
(keychain/can-save-user-password?
(fn [can-save?]
(when (and can-save? (not android-device-blacklisted?))
(-> (biometrics/get-supported-type)
(.then (fn [type]
(rf/dispatch [:biometric/get-supported-biometric-type-success type])))))))))
(rf/defn get-supported-biometric-auth-success
{:events [:biometric/get-supported-biometric-type-success]}
[{:keys [db]} supported-type]
{:db (assoc db :biometric/supported-type supported-type)})
(rf/defn show-message
{:events [:biometric/show-message]}
[_ error]
(let [code (ex-cause error)
content (if (#{::biometrics/not-enrolled
::biometrics/not-available}
(defn show-message
[_ [code]]
(let [content (if (#{:biometrics/not-enrolled-error
:biometrics/not-available-error}
code)
(i18n/label :t/grant-face-id-permissions)
(i18n/label :t/biometric-auth-error {:code code}))]
{:effects.utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content content}}))
{:fx [[:effects.utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content content}]]}))
(rf/reg-event-fx :biometric/show-message show-message)
(re-frame/reg-fx
:biometric/authenticate
(fn [{:keys [on-success on-fail prompt-message]}]
(-> (biometrics/authenticate
{:prompt-message (or prompt-message (i18n/label :t/biometric-auth-reason-login))
:fallback-prompt-message (i18n/label
:t/biometric-auth-login-ios-fallback-label)
:cancel-button-text (i18n/label :t/cancel)})
(.then (fn [not-canceled?]
(when (and on-success not-canceled?)
(on-success))))
(.catch (fn [err]
(when on-fail
(on-fail err)))))))
(defn on-authentication-done
[{:keys [db]}]
{:db (assoc-in db [:biometrics :auth-pending?] false)})
(rf/defn authenticate
{:events [:biometric/authenticate]}
[_ opts]
{:biometric/authenticate opts})
(rf/reg-event-fx :biometric/on-authentication-done on-authentication-done)
(rf/reg-event-fx
:biometric/on-enable-success
(fn [{:keys [db]} [password]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-biometric)
:dispatch [:keychain/save-password-and-auth-method
{:key-uid key-uid
:masked-password password}]})))
(defn authenticate
[{:keys [db]} [opts]]
(let [pending? (get-in db [:biometrics :auth-pending?])]
;;NOTE: prompting biometric check while another one is pending triggers error
(when-not pending?
{:db (assoc-in db [:biometrics :auth-pending?] true)
:fx [[:effects.biometric/authenticate
(assoc opts :on-done #(rf/dispatch [:biometric/on-authentication-done]))]]})))
(rf/reg-event-fx
:biometric/enable
(fn [_ [password]]
{:dispatch [:biometric/authenticate
{:on-success #(rf/dispatch [:biometric/on-enable-success password])
:on-fail #(rf/dispatch [:biometric/show-message %])}]}))
(rf/reg-event-fx :biometric/authenticate authenticate)
(rf/reg-event-fx
:biometric/disable
(fn [{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-none)
:keychain/clear-user-password key-uid})))
(defn enable-biometrics
[{:keys [db]} [password]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-biometric)
:fx [[:dispatch
[:keychain/save-password-and-auth-method
{:key-uid key-uid
:masked-password password}]]]}))
(rf/reg-event-fx :biometric/enable enable-biometrics)
(defn disable-biometrics
[{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-none)
:fx [[:keychain/clear-user-password key-uid]]}))
(rf/reg-event-fx :biometric/disable disable-biometrics)
(rf/reg-fx
:biometric/check-if-available
(fn [[key-uid callback]]
(keychain/can-save-user-password?
(fn [can-save?]
(when can-save?
(-> (biometrics/get-available)
(.then (fn [available?]
(when-not available?
(throw (js/Error. "biometric-not-available")))))
(.then #(keychain/get-auth-method! key-uid))
(.then (fn [auth-method]
(when auth-method (callback auth-method))))
(.catch (fn [err]
(when-not (= (.-message err) "biometric-not-available")
(log/error "Failed to check if biometrics is available"
{:error err
:key-uid key-uid
:event :profile.login/check-biometric}))))))))))
@@ -0,0 +1,68 @@
(ns status-im.common.biometric.events-test
(:require [cljs.test :refer [deftest is testing]]
matcher-combinators.test
[status-im.common.biometric.events :as sut]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.security.core :as security]))
(deftest set-supported-biometrics-type-test
(testing "successfully setting supported biometrics type"
(let [cofx {:db {}}
supported-type constants/biometrics-type-face-id
expected {:db (assoc-in (:db cofx) [:biometrics :supported-type] supported-type)}]
(is (match? expected (sut/set-supported-type cofx [supported-type]))))))
(deftest show-message-test
(testing "informs the user to enable biometrics from settings"
(let [cofx {:db {}}
expected {:fx [[:effects.utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content (i18n/label :t/grant-face-id-permissions)}]]}]
(is (match? expected
(sut/show-message cofx
[:biometrics/not-available-error])))))
(testing "shows a generic error message"
(let [cofx {:db {}}
error-cause :test-error
expected {:fx [[:effects.utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content (i18n/label :t/biometric-auth-error {:code error-cause})}]]}]
(is (match? expected
(sut/show-message cofx
[error-cause]))))))
(deftest authenticate-biometrics-test
(testing "passing the right args to authenticate"
(let [cofx {:db {}}
args {:on-success identity
:on-fail identity
:prompt-message "test"}
result (sut/authenticate cofx [args])]
(is (= (:prompt-message args) (get-in result [:fx 0 1 :prompt-message])))
(is (not (nil? (get-in result [:fx 0 1 :on-success]))))
(is (not (nil? (get-in result [:fx 0 1 :on-fail]))))))
(testing "skips biometric check if another one pending"
(let [cofx {:db {:biometrics {:auth-pending? true}}}
result (sut/authenticate cofx [{}])]
(is (nil? result)))))
(deftest enable-biometrics-test
(testing "successfully enabling biometrics"
(let [key-uid "test-uid"
password (security/mask-data "test-pw")
cofx {:db {:profile/profile {:key-uid key-uid}}}
expected-db (assoc (:db cofx) :auth-method constants/auth-method-biometric)
result (sut/enable-biometrics cofx [password])]
(is (match? expected-db (:db result)))
(is (= password (get-in result [:fx 0 1 1 :masked-password]))))))
(deftest disable-biometrics-test
(testing "successfully disabling biometrics"
(let [key-uid "test-uid"
cofx {:db {:profile/profile {:key-uid key-uid}}}
expected {:db (assoc (:db cofx) :auth-method constants/auth-method-none)
:fx [[:keychain/clear-user-password key-uid]]}]
(is (match? expected (sut/disable-biometrics cofx))))))
+22
View File
@@ -0,0 +1,22 @@
(ns status-im.common.biometric.utils
(:require
[native-module.core :as native-module]
[react-native.platform :as platform]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
(def android-device-blacklisted?
(and platform/android? (= (:brand (native-module/get-device-model-info)) "bannedbrand")))
(defn get-label-by-type
[biometric-type]
(condp = biometric-type
constants/biometrics-type-android (i18n/label :t/biometric-fingerprint)
constants/biometrics-type-face-id (i18n/label :t/biometric-faceid)
(i18n/label :t/biometric-touchid)))
(defn get-icon-by-type
[biometric-type]
(condp = biometric-type
constants/biometrics-type-face-id :i/face-id
:i/touch-id))
+12 -11
View File
@@ -3,18 +3,18 @@
[quo.foundations.colors :as colors]
[react-native.platform :as platform]))
(def ^:private sheet-border-radius 20)
(defn sheet
[{:keys [top]} window-height selected-item]
[{:keys [max-height]}]
{:position :absolute
:max-height (- window-height top)
:z-index 1
:bottom 0
:left 0
:right 0
:border-top-left-radius 20
:border-top-right-radius 20
:overflow (when-not selected-item :hidden)
:flex 1})
:z-index 1
:max-height max-height
:border-top-left-radius sheet-border-radius
:border-top-right-radius sheet-border-radius})
(def gradient-bg
{:position :absolute
@@ -31,10 +31,11 @@
:bottom 0})
(defn sheet-content
[theme padding-bottom-override {:keys [bottom]} shell? bottom-margin]
{:border-top-left-radius 20
:border-top-right-radius 20
:padding-bottom (or padding-bottom-override (+ bottom bottom-margin))
[{:keys [theme padding-bottom shell?]}]
{:overflow :scroll
:padding-bottom padding-bottom
:border-top-left-radius sheet-border-radius
:border-top-right-radius sheet-border-radius
:background-color (if shell?
:transparent
(colors/theme-colors colors/white colors/neutral-95 theme))})
+20 -12
View File
@@ -56,6 +56,10 @@
(show translate-y bg-opacity)
(hide translate-y bg-opacity window-height on-close))))))
(defn- get-layout-height
[event]
(oops/oget event "nativeEvent.layout.height"))
(defn view
[{:keys [hide? insets]}
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
@@ -64,6 +68,8 @@
(let [theme (quo.theme/use-theme-value)
sheet-height (rn/use-ref-atom 0)
item-height (rn/use-ref-atom 0)
set-sheet-height (rn/use-callback #(reset! sheet-height (get-layout-height %)))
set-item-height (rn/use-callback #(reset! item-height (get-layout-height %)))
{window-height :height} (rn/get-window)
bg-opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value window-height)
@@ -80,7 +86,10 @@
top (- window-height (:top insets) @sheet-height)
bottom (if selected-item-smaller-than-sheet?
(+ @sheet-height bottom-margin)
(:bottom insets))]
(:bottom insets))
sheet-max-height (- window-height (:top insets))
content-padding-bottom (or padding-bottom-override
(+ (:bottom insets) bottom-margin))]
(rn/use-effect
#(if hide?
(hide translate-y bg-opacity window-height on-close)
@@ -105,7 +114,7 @@
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
(style/sheet insets window-height selected-item))}
(style/sheet {:max-height sheet-max-height}))}
(when shell?
[blur/ios-view
{:style style/shell-bg
@@ -114,19 +123,18 @@
:overlay-color :transparent}])
(when selected-item
[rn/view
{:on-layout #(reset! item-height (.-nativeEvent.layout.height ^js %))
:style
(style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)}
{:on-layout set-item-height
:style (style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)}
[selected-item]])
[rn/view
{:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin)
:on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))}
{:on-layout set-sheet-height
:style (style/sheet-content {:theme theme
:shell? shell?
:padding-bottom content-padding-bottom})}
(when (and gradient-cover? customization-color)
[rn/view {:style style/gradient-bg}
[quo/gradient-cover
{:customization-color customization-color
:opacity 0.4}]])
[quo/gradient-cover
{:customization-color customization-color
:opacity 0.4}])
(when-not hide-handle?
[quo/drawer-bar])
[content]]]]]))
@@ -2,14 +2,12 @@
(:require
[quo.foundations.colors :as colors]
[quo.theme :as theme]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]))
(defn container
[{:keys [top] :as _insets}]
(let [padding-top (if platform/ios? top (+ top 10))]
{:flex 1
:padding-top padding-top}))
[padding-top]
{:flex 1
:padding-top padding-top})
(defn background
[opacity]
@@ -49,21 +49,24 @@
set-animating-false (fn [ms]
(js/setTimeout #(reset! animating? false) ms))]
(fn [{:keys [content skip-background? theme]}]
(let [insets (safe-area/get-insets)
{:keys [height]} (rn/get-window)
opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value height)
close (fn []
(set-animating-true)
(reanimated/animate translate-y height 300)
(reanimated/animate opacity 0 300)
(rf/dispatch [:navigate-back])
true)
reset-open-sheet (fn []
(reanimated/animate translate-y 0 300)
(reanimated/animate opacity 1 300)
(set-animating-false 300)
(reset! scroll-enabled? true))]
(let [{:keys [top] :as insets} (safe-area/get-insets)
alert-banners-top-margin (rf/sub [:alert-banners/top-margin])
padding-top (+ alert-banners-top-margin
(if platform/ios? top (+ top 10)))
{:keys [height]} (rn/get-window)
opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value height)
close (fn []
(set-animating-true)
(reanimated/animate translate-y height 300)
(reanimated/animate opacity 0 300)
(rf/dispatch [:navigate-back])
true)
reset-open-sheet (fn []
(reanimated/animate translate-y 0 300)
(reanimated/animate opacity 1 300)
(set-animating-false 300)
(reset! scroll-enabled? true))]
(rn/use-mount
(fn []
(rn/hw-back-add-listener close)
@@ -71,7 +74,7 @@
(reanimated/animate opacity 1 300)
(set-animating-false 300)
#(rn/hw-back-remove-listener close)))
[rn/view {:style (style/container insets)}
[rn/view {:style (style/container padding-top)}
(when-not skip-background?
[reanimated/view {:style (style/background opacity)}])
[gesture/gesture-detector
@@ -52,7 +52,8 @@
:remove-listeners remove-listeners}))
(defn view
[{:keys [header footer customization-color footer-container-padding gradient-cover?]
[{:keys [header footer customization-color footer-container-padding header-container-style
gradient-cover?]
:or {footer-container-padding (safe-area/get-top)}} &
children]
(reagent/with-let [window-height (:height (rn/get-window))
@@ -85,7 +86,9 @@
[:<>
(when gradient-cover? [quo/gradient-cover {:customization-color customization-color}])
[rn/view {:style style/page-container}
[rn/view {:on-layout set-header-height}
[rn/view
{:on-layout set-header-height
:style header-container-style}
header]
[rn/scroll-view
{:on-scroll set-content-y-scroll
@@ -0,0 +1,18 @@
(ns status-im.common.parallax.blacklist
(:require
[native-module.core :as native-module]))
(def ^:private device-id (:device-id (native-module/get-device-model-info)))
(defn- get-model-code
[model]
(if-let [[_ code] (and model (re-find #"iPhone(\d+)" model))]
(js/parseInt code 10)
0))
(def ^:private minimum-device-code 11)
(def blacklisted?
(-> device-id
get-model-code
(< minimum-device-code)))
@@ -1,13 +0,0 @@
(ns status-im.common.parallax.whitelist
(:require
[clojure.string :as string]
[native-module.core :as native-module]))
(def ^:const device-id (:device-id (native-module/get-device-model-info)))
;; iPhone 14 is 15 for some reason
(def ^:const whitelist #{"iPhone11" "iPhone12" "iPhone13" "iPhone14" "iPhone15"})
(def whitelisted?
(let [device-type (first (string/split (str device-id) ","))]
(whitelist device-type)))
@@ -1,11 +1,93 @@
(ns status-im.common.standard-authentication.events
(:require
[utils.re-frame :as rf]))
[schema.core :as schema]
[status-im.common.standard-authentication.enter-password.view :as enter-password]
[status-im.common.standard-authentication.events-schema :as events-schema]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :standard-auth/on-biometric-success
(fn [{:keys [db]} [callback]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:keychain/get-user-password [key-uid callback]]]})))
(defn authorize
[{:keys [db]} [args]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success #(rf/dispatch [:standard-auth/authorize-with-biometric args])
:on-fail #(rf/dispatch [:standard-auth/authorize-with-password args])}]]}))
(schema/=> authorize events-schema/?authorize)
(rf/reg-event-fx :standard-auth/authorize authorize)
(defn authorize-with-biometric
[_ [{:keys [on-auth-success on-auth-fail] :as args}]]
(let [args-with-biometric-btn
(assoc args
:on-press-biometric
#(rf/dispatch [:standard-auth/authorize-with-biometric args]))]
{:fx [[:dispatch [:dismiss-keyboard]]
[:dispatch
[:biometric/authenticate
{:prompt-message (i18n/label :t/biometric-auth-confirm-message)
:on-cancel #(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
:on-success #(rf/dispatch [:standard-auth/on-biometric-success on-auth-success])
:on-fail (fn [err]
(when on-auth-fail (on-auth-fail err))
(rf/dispatch [:standard-auth/on-biometric-fail err]))}]]]}))
(schema/=> authorize-with-biometric events-schema/?authorize-with-biometric)
(rf/reg-event-fx :standard-auth/authorize-with-biometric authorize-with-biometric)
(defn on-biometric-success
[{:keys [db]} [on-auth-success]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:keychain/get-user-password [key-uid on-auth-success]]
[:dispatch [:standard-auth/reset-login-password]]]}))
(schema/=> on-biometric-success events-schema/?on-biometric-success)
(rf/reg-event-fx :standard-auth/on-biometric-success on-biometric-success)
(defn on-biometric-fail
[_ [error]]
(log/error (ex-message error)
(-> error
ex-data
(assoc :code (ex-cause error)
:event :standard-auth/on-biometric-fail)))
{:fx [[:dispatch [:standard-auth/reset-login-password]]
[:dispatch [:biometric/show-message (ex-cause error)]]]})
(schema/=> on-biometric-fail events-schema/?on-biometrics-fail)
(rf/reg-event-fx :standard-auth/on-biometric-fail on-biometric-fail)
(defn- bottom-sheet-password-view
[{:keys [on-press-biometric on-auth-success auth-button-icon-left auth-button-label]}]
(fn []
(let [handle-password-success (fn [password]
(rf/dispatch [:standard-auth/reset-login-password])
(-> password security/hash-masked-password on-auth-success))]
[enter-password/view
{:on-enter-password handle-password-success
:on-press-biometrics on-press-biometric
:button-icon-left auth-button-icon-left
:button-label auth-button-label}])))
(defn authorize-with-password
[_ [{:keys [on-close theme blur?] :as args}]]
{:fx [[:dispatch [:standard-auth/reset-login-password]]
[:dispatch
[:show-bottom-sheet
{:on-close (fn []
(rf/dispatch [:standard-auth/reset-login-password])
(when on-close
(on-close)))
:theme theme
:shell? blur?
:content #(bottom-sheet-password-view args)}]]]})
(schema/=> authorize-with-password events-schema/?authorize-with-password)
(rf/reg-event-fx :standard-auth/authorize-with-password authorize-with-password)
(rf/reg-event-fx
:standard-auth/reset-login-password

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