Compare commits

..
Author SHA1 Message Date
kaichaosun 9f7074ff69 chore_: rebase status-go 2024-06-25 15:42:41 +08:00
443 changed files with 7921 additions and 13910 deletions
+2
View File
@@ -4,6 +4,7 @@ DEFAULT_NETWORK=mainnet_rpc
DEV_BUILD=1
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
@@ -25,6 +26,7 @@ APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
COMMANDS_ENABLED=1
TWO_MINUTES_SYNCING=1
SWAP_ENABLED=1
+1 -1
View File
@@ -2,7 +2,7 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.staging
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=0
+1
View File
@@ -3,6 +3,7 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=1
+1
View File
@@ -2,6 +2,7 @@ DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
+2
View File
@@ -2,6 +2,7 @@ DEBUG_WEBVIEW=0
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=
MAILSERVER_CONFIRMATIONS_ENABLED=1
@@ -17,5 +18,6 @@ PARTITIONED_TOPIC=0
ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
+1 -1
View File
@@ -2,7 +2,7 @@
name: MVPBug Report
about: MVPBug Report
title: ''
labels: ['E:Mobile Bug MVP', ':1234: low prio']
labels: 'E:Mobile Bug MVP'
assignees: ''
---
+9 -14
View File
@@ -1,15 +1,10 @@
/*
# Format top-level js files.
*
!*.js
# Ignore all except src/js/**/*.js
!/src/
/src/*
!/src/js
!/src/js/**/*.js
# Ignore all except translations/en.json
!/translations/
/translations/*
!/translations/en.json
!*/
*.clj-kondo
*.shadow-cljs
modules
result
target
component-spec
/app
-4
View File
@@ -6,8 +6,4 @@ module.exports = {
tabWidth: 2,
trailingComma: 'all',
useTabs: false,
// JSON sorting
jsonSortOrder: '{ "/.*/": "caseInsensitiveLexical" } ',
plugins: ['prettier-plugin-sort-json'],
};
+1 -7
View File
@@ -317,7 +317,7 @@ lint: ##@test Run code style checks
scripts/lint/translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \
node_modules/.bin/prettier --check .
node_modules/.bin/prettier --write .
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
lint-fix: export TARGET := clojure
@@ -457,12 +457,6 @@ android-tail-geth: export VERSION ?= debug
android-tail-geth:
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-clean-geth: export TARGET := android-sdk
android-clean-geth: export VERSION ?= debug
android-clean-geth:
adb shell 'rm /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-logcat: export TARGET := android-sdk
android-logcat: ##@other Read status-mobile logs from Android phone using adb
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -71,7 +71,7 @@ pipeline {
}
stage('Upload') {
steps { script {
def urls = apks.collect { s5cmd.upload(it) }
def urls = apks.collect { s3.uploadArtifact(it) }
if (urls.size() > 1) { /* Return only the universal APK. */
env.PKG_URL = urls.find { it.contains('universal') }
} else { /* If no universal is available pick first. */
+3 -24
View File
@@ -1,7 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
import groovy.json.JsonBuilder
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent { label 'linux' }
@@ -74,7 +72,7 @@ pipeline {
iOS: utils.pkgUrl(ios),
Diawi: utils.getEnv(ios, 'DIAWI_URL'),
/* upload the sha256 checksums file too */
SHA: s5cmd.upload(sha),
SHA: s3.uploadArtifact(sha),
]
/* add URLs to the build description */
jenkins.setBuildDesc(urls)
@@ -85,7 +83,7 @@ pipeline {
steps { script {
switch (utils.getBuildType()) {
case 'nightly': /* Create JSON file with newest build URLs */
updateBucketJSON(urls, 'latest.json');
s3.updateBucketJSON(urls, 'latest.json');
break;
case 'release':
github.publishReleaseFiles(repo: 'status-mobile');
@@ -116,22 +114,3 @@ def Boolean getPublishDefault(Boolean previousValue) {
if (previousValue != null) { return previousValue }
return false
}
/* Helper for updating JSON with newest builds. */
def updateBucketJSON(urls, fileName) {
/* latest.json has slightly different key names */
def content = [
DIAWI: urls.Diawi,
APK: urls.Apk, IOS: urls.iOS,
APP: urls.App, MAC: urls.Mac,
WIN: urls.Win, SHA: urls.SHA
]
def filePath = "${pwd()}/pkg/${fileName}"
/* it might not exist */
sh "mkdir -p ${pwd()}/pkg"
def contentJson = new JsonBuilder(content).toPrettyString()
println "${filePath}:\n${contentJson}"
writeFile(file: filePath, text: contentJson)
return s5cmd.upload(filePath)
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -75,7 +75,7 @@ pipeline {
stage('Upload') {
steps {
script {
env.PKG_URL = s5cmd.upload(LOG_FILE)
env.PKG_URL = s3.uploadArtifact(LOG_FILE)
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
@@ -99,7 +99,7 @@ pipeline {
--rerun_count=2 \
--testrail_report=True \
-m testrail_id \
-m \"nightly\" \
-m \"new_ui_critical or new_ui_medium\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_URL ?: apk_path}
"""
+4 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
@@ -35,11 +35,13 @@ pipeline {
description: 'OBSOLETE ARGUMENT TO BE REMOVED',
defaultValue: 'DUMMY',
)
/* Commented to use TEST_MARKERS values from job params
string(
name: 'TEST_MARKERS',
description: 'Marker expression for matching tests to run.',
defaultValue: 'smoke',
defaultValue: 'new_ui_critical',
)
*/
}
options {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent { label 'macos' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent { label params.AGENT_LABEL }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.8.12'
pipeline {
agent {
+3 -5
View File
@@ -32,16 +32,14 @@ status-mobile code that makes it to the `develop` branch, should always point to
In practice, this means that sometimes they need to be merged in lockstep.
1) Create a PR in status-go and status-mobile. Update the status-go version to the PR revision `scripts/update-status-go.sh $git_revision`.
2) Get both PRs reviewed and approved. Once status-mobile PR has been approved, go through manual QA testing if necessary. Don't merge status-mobile PR just yet.
3) Now that you know the integration between client & server is working, merge the status-go PR first.
4) Once merged, tag the merged commit with the new version and push the tag:
3) Now that you know the integration between client & server is working, bump the `VERSION` in status-go and merge it.
4) Once merged, tag the version with the new version and push the tag:
```
git checkout develop
git pull develop
make tag-version
git tag vx.y.z
git push origin vx.y.z
```
:warning: If a specific commit need to tagged in status-go, use `make tag-version TARGET_COMMIT={hash}`. More info about tagging in [status-go](https://github.com/status-im/status-go/blob/develop/RELEASING.md#tagging-versions).
5) Update status-mobile with the new status-go version, using the new tag `scripts/update-status-go.sh "vx.y.z"`
6) If you had to rebase status-go to include new changes, e2e test MUST be re-run. If there's any issue you will
have to fix in status-go with another PR and follow the same process.
+2 -2
View File
@@ -31,7 +31,7 @@ NOW:
(defn view
[{:keys [on-press on-long-press icon]}]
(let [[pressed? set-pressed] (rn/use-state false)
theme (theme/use-theme)
theme (theme/use-theme-value)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
@@ -47,7 +47,7 @@ NOW:
- We no longer need to create an anonymous function for rendering. This removes unnecessary confusion and the need for specific knowledge on how it works and why it was needed.
- `rn/use-state` is used instead of `reagent/atom`
- State values no longer need to be dereferenced; they are accessible as regular symbols. This eliminates a common bug where the "@" symbol was inadvertently omitted.
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme)` hook can be used directly in the components
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme-value)` hook can be used directly in the components
- `:f>` not needed anymore, all components are functional by default
- `rn/use-callback` hook should be used for anon callback functions
+2 -2
View File
@@ -915,7 +915,7 @@ PODS:
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- react-native-compat (2.11.2):
- react-native-compat (2.12.2):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
@@ -1517,7 +1517,7 @@ SPEC CHECKSUMS:
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: 799045500f56146afc46245148080e7b7623cb75
react-native-cameraroll: af8eec1e585d053ff485d98ec837f9a8a11b5745
react-native-compat: 3af9add14d349701306d3d052638435f6795ac2c
react-native-compat: 84e00e8dcff9251278c0d48f2bce81f4502e3925
react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
react-native-hole-view: 6935448993bac79f2b5a4ad7e9741094cf810679
+3 -1
View File
@@ -119,6 +119,8 @@
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
@@ -131,7 +133,7 @@
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<false/>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A00000080400010101</string>
@@ -246,14 +246,6 @@ class AccountManager(private val reactContext: ReactApplicationContext) : ReactC
utils.executeRunnableStatusGoMethod({ Statusgo.openAccounts(rootDir) }, callback)
}
@ReactMethod
private fun initializeApplication(request: String, callback: Callback) {
Log.d(TAG, "initializeApplication")
Log.d(TAG, "[Initializing application $request")
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
}
@ReactMethod
fun logout() {
Log.d(TAG, "logout")
@@ -92,11 +92,6 @@ public class EncryptionUtils extends ReactContextBaseJavaModule {
return Statusgo.hexToUtf8(str);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String serializeLegacyKey(final String publicKey) {
return Statusgo.serializeLegacyKey(publicKey);
}
@ReactMethod
public void setBlankPreviewFlag(final Boolean blankPreview) {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.reactContext);
@@ -76,16 +76,6 @@ class StatusModule(private val reactContext: ReactApplicationContext, private va
utils.executeRunnableStatusGoMethod({ Statusgo.getNodeConfig() }, callback)
}
@ReactMethod
fun addCentralizedMetric(request: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.addCentralizedMetric(request) }, callback)
}
@ReactMethod
fun toggleCentralizedMetrics(request: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.toggleCentralizedMetrics(request) }, callback)
}
@ReactMethod
fun deleteImportedKey(keyUID: String, address: String, password: String, callback: Callback) {
val keyStoreDir = utils.getKeyStorePath(keyUID)
@@ -153,9 +153,4 @@ class Utils(private val reactContext: ReactApplicationContext) : ReactContextBas
return strArray
}
@ReactMethod(isBlockingSynchronousMethod = true)
fun validateConnectionString(connectionString: String): String {
return Statusgo.validateConnectionString(connectionString)
}
}
@@ -195,15 +195,6 @@ RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
callback(@[result]);
}
RCT_EXPORT_METHOD(initializeApplication:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"initializeApplication() method called");
#endif
NSString *result = StatusgoInitializeApplication(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"OpenAccounts() method called");
@@ -94,10 +94,6 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hexToUtf8:(NSString *)str) {
return StatusgoHexToUtf8(str);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(serializeLegacyKey:(NSString *)str) {
return StatusgoSerializeLegacyKey(str);
}
RCT_EXPORT_METHOD(setBlankPreviewFlag:(BOOL *)newValue)
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
@@ -176,24 +176,6 @@ RCT_EXPORT_METHOD(appStateChange:(NSString *)type) {
StatusgoAppStateChange(type);
}
RCT_EXPORT_METHOD(addCentralizedMetric:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"addCentralizedMetric() method called");
#endif
NSString *result = StatusgoAddCentralizedMetric(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(toggleCentralizedMetrics:(NSString *)request
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"toggleCentralizedMetrics() method called");
#endif
NSString *result = StatusgoToggleCentralizedMetrics(request);
callback(@[result]);
}
RCT_EXPORT_METHOD(startLocalNotifications) {
#if DEBUG
NSLog(@"StartLocalNotifications() method called");
@@ -128,8 +128,4 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(validateConnectionString:(NSString *)cs) {
return StatusgoValidateConnectionString(cs);
}
@end
+1 -65
View File
@@ -302,36 +302,6 @@ void _MultiAccountStoreAccount(const FunctionCallbackInfo<Value>& args) {
delete c;
}
void _InitializeApplication(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for InitializeApplication")));
return;
}
// Check the argument types
if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for request")));
return;
}
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;
// Call exported Go function, which returns a C string
char *c = InitializeApplication(arg0);
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}
void _InitKeystore(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
@@ -672,38 +642,6 @@ void _Sha3(const FunctionCallbackInfo<Value>& args) {
}
void _SerializeLegacyKey(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 SerializeLegacyKey")));
return;
}
// Check the argument types
if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'str'")));
return;
}
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
char *arg0 = *arg0Obj;
// Call exported Go function, which returns a C string
char *c = SerializeLegacyKey(arg0);
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
args.GetReturnValue().Set(ret);
delete c;
}
void _ToChecksumAddress(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
@@ -1997,7 +1935,6 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "multiAccountStoreDerivedAccounts", _MultiAccountStoreDerivedAccounts);
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
NODE_SET_METHOD(exports, "fleets", _Fleets);
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
@@ -2008,7 +1945,6 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "checkAddressChecksum", _CheckAddressChecksum);
NODE_SET_METHOD(exports, "isAddress", _IsAddress);
NODE_SET_METHOD(exports, "sha3", _Sha3);
NODE_SET_METHOD(exports, "serializeLegacyKey", _SerializeLegacyKey);
NODE_SET_METHOD(exports, "toChecksumAddress", _ToChecksumAddress);
NODE_SET_METHOD(exports, "logout", _Logout);
NODE_SET_METHOD(exports, "hashMessage", _HashMessage);
@@ -2036,7 +1972,7 @@ void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "signTypedData", _SignTypedData);
NODE_SET_METHOD(exports, "sendTransaction", _SendTransaction);
NODE_SET_METHOD(exports, "appStateChange", _AppStateChange);
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
NODE_SET_METHOD(exports, "validateNodeConfig", _ValidateNodeConfig);
NODE_SET_METHOD(exports, "hashTypedData", _HashTypedData);
NODE_SET_METHOD(exports, "recover", _Recover);
+1 -1
View File
@@ -57,7 +57,7 @@ in {
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
openjdk = super.openjdk11_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
versions = ["15.1" "15.2" "15.3" "15.4"];
versions = ["15.1" "15.2" "15.3"];
};
go = super.go_1_21;
clang = super.clang_15;
+3 -5
View File
@@ -20,10 +20,9 @@
"@react-native-community/netinfo": "^4.4.0",
"@react-native-community/push-notification-ios": "^1.4.1",
"@react-native-community/slider": "^3.0.0",
"@walletconnect/react-native-compat": "2.11.2",
"@walletconnect/web3wallet": "1.10.2",
"@walletconnect/react-native-compat": "^2.12.2",
"@walletconnect/web3wallet": "^1.11.2",
"base-64": "^1.0.0",
"big-integer": "1.6.51",
"bignumber.js": "git+https://github.com/status-im/bignumber.js.git#refs/tags/v4.0.2-status",
"chance": "^1.1.0",
"emojilib": "^2.4.0",
@@ -97,8 +96,7 @@
"jest-silent-reporter": "^0.5.0",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
"prettier": "^3.3.3",
"prettier-plugin-sort-json": "^4.0.0",
"prettier": "^2.8.8",
"process": "0.11.10",
"react-test-renderer": "18.1.0",
"shadow-cljs": "2.26.2",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

-2
View File
@@ -45,8 +45,6 @@ SECRETS_ENV_VARS=(
'INFURA_TOKEN'
'INFURA_TOKEN_SECRET'
'OPENSEA_API_KEY'
'MIXPANEL_APP_ID'
'MIXPANEL_TOKEN'
'POKT_TOKEN'
)
-6
View File
@@ -67,8 +67,6 @@
:closure-defines
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
@@ -104,8 +102,6 @@
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
@@ -147,8 +143,6 @@
status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
+37 -276
View File
@@ -1,277 +1,38 @@
(ns keycard.keycard
(:require
["react-native" :as rn]
["react-native-status-keycard" :default status-keycard]
[react-native.platform :as platform]
[taoensso.timbre :as log]
[utils.address :as address]))
(ns keycard.keycard)
(defonce event-emitter
(if platform/ios?
(new (.-NativeEventEmitter rn) status-keycard)
(.-DeviceEventEmitter rn)))
(defn start-nfc
[{:keys [on-success on-failure prompt-message]}]
(log/debug "start-nfc")
(.. status-keycard
(startNFC (str prompt-message))
(then on-success)
(catch on-failure)))
(defn stop-nfc
[{:keys [on-success on-failure error-message]}]
(log/debug "stop-nfc")
(.. status-keycard
(stopNFC (str error-message))
(then on-success)
(catch on-failure)))
(defn set-nfc-message
[{:keys [on-success on-failure status-message]}]
(log/debug "set-nfc-message")
(.. status-keycard
(setNFCMessage (str status-message))
(then on-success)
(catch on-failure)))
(defn check-nfc-support
[{:keys [on-success]}]
(.. status-keycard
nfcIsSupported
(then on-success)))
(defn check-nfc-enabled
[{:keys [on-success]}]
(.. status-keycard
nfcIsEnabled
(then on-success)))
(defn open-nfc-settings
[]
(.openNfcSettings status-keycard))
(defn remove-event-listeners
[]
(doseq [event ["keyCardOnConnected" "keyCardOnDisconnected" "keyCardOnNFCUserCancelled"
"keyCardOnNFCTimeout"]]
(.removeAllListeners ^js event-emitter event)))
(defn remove-event-listener
[^js event]
(when event
(.remove event)))
(defn on-card-connected
[callback]
(.addListener ^js event-emitter "keyCardOnConnected" callback))
(defn on-card-disconnected
[callback]
(.addListener ^js event-emitter "keyCardOnDisconnected" callback))
(defn on-nfc-user-cancelled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCUserCancelled" callback))
(defn on-nfc-timeout
[callback]
(.addListener ^js event-emitter "keyCardOnNFCTimeout" callback))
(defn on-nfc-enabled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCEnabled" callback))
(defn on-nfc-disabled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCDisabled" callback))
(defn set-pairings
[pairings]
(.. status-keycard (setPairings (clj->js (or pairings {})))))
(defn get-application-info
[{:keys [on-success on-failure]}]
(.. status-keycard
(getApplicationInfo)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(catch on-failure)))
(defn factory-reset
[{:keys [on-success on-failure]}]
(.. status-keycard
(factoryReset)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(catch on-failure)))
(defn install-applet
[{:keys [on-success on-failure]}]
(.. status-keycard
installApplet
(then on-success)
(catch on-failure)))
(defn install-cash-applet
[{:keys [on-success on-failure]}]
(.. status-keycard
installCashApplet
(then on-success)
(catch on-failure)))
(defn init-card
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(init pin)
(then on-success)
(catch on-failure)))
(defn install-applet-and-init-card
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(installAppletAndInitCard pin)
(then on-success)
(catch on-failure)))
(defn pair
[{:keys [password on-success on-failure]}]
(when password
(.. status-keycard
(pair password)
(then on-success)
(catch on-failure))))
(defn generate-and-load-key
[{:keys [mnemonic pin on-success on-failure]}]
(.. status-keycard
(generateAndLoadKey mnemonic pin)
(then on-success)
(catch on-failure)))
(defn unblock-pin
[{:keys [puk new-pin on-success on-failure]}]
(when (and new-pin puk)
(.. status-keycard
(unblockPin puk new-pin)
(then on-success)
(catch on-failure))))
(defn verify-pin
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(verifyPin pin)
(then on-success)
(catch on-failure))))
(defn change-pin
[{:keys [current-pin new-pin on-success on-failure]}]
(when (and current-pin new-pin)
(.. status-keycard
(changePin current-pin new-pin)
(then on-success)
(catch on-failure))))
(defn change-puk
[{:keys [pin puk on-success on-failure]}]
(when (and pin puk)
(.. status-keycard
(changePUK pin puk)
(then on-success)
(catch on-failure))))
(defn change-pairing
[{:keys [pin pairing on-success on-failure]}]
(when (and pin pairing)
(.. status-keycard
(changePairingPassword pin pairing)
(then on-success)
(catch on-failure))))
(defn unpair
[{:keys [pin on-success on-failure]}]
(when pin
(.. status-keycard
(unpair pin)
(then on-success)
(catch on-failure))))
(defn delete
[{:keys [on-success on-failure]}]
(.. status-keycard
(delete)
(then on-success)
(catch on-failure)))
(defn remove-key
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(removeKey pin)
(then on-success)
(catch on-failure)))
(defn remove-key-with-unpair
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(removeKeyWithUnpair pin)
(then on-success)
(catch on-failure)))
(defn export-key
[{:keys [pin path on-success on-failure]}]
(.. status-keycard
(exportKeyWithPath pin path)
(then on-success)
(catch on-failure)))
(defn unpair-and-delete
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(unpairAndDelete pin)
(then on-success)
(catch on-failure))))
(defn import-keys
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(importKeys pin)
(then on-success)
(catch on-failure))))
(defn get-keys
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(getKeys pin)
(then on-success)
(catch on-failure))))
(defn sign
[{pin :pin path :path card-hash :hash on-success :on-success on-failure :on-failure}]
(when (and pin card-hash)
(if path
(.. status-keycard
(signWithPath pin path card-hash)
(then on-success)
(catch on-failure))
(.. status-keycard
(sign pin card-hash)
(then on-success)
(catch on-failure)))))
(defn sign-typed-data
[{card-hash :hash on-success :on-success on-failure :on-failure}]
(when card-hash
(.. status-keycard
(signPinless card-hash)
(then on-success)
(catch on-failure))))
(defprotocol Keycard
(start-nfc [this args])
(stop-nfc [this args])
(set-nfc-message [this args])
(check-nfc-support [this args])
(check-nfc-enabled [this args])
(open-nfc-settings [this])
(register-card-events [this args])
(set-pairings [this args])
(on-card-disconnected [this callback])
(on-card-connected [this callback])
(remove-event-listener [this event])
(remove-event-listeners [this])
(get-application-info [this args])
(factory-reset [this args])
(install-applet [this args])
(install-cash-applet [this args])
(init-card [this args])
(install-applet-and-init-card [this args])
(pair [this args])
(generate-and-load-key [this args])
(unblock-pin [this args])
(verify-pin [this args])
(change-pin [this args])
(change-puk [this args])
(change-pairing [this args])
(unpair [this args])
(delete [this args])
(remove-key [this args])
(remove-key-with-unpair [this args])
(export-key [this args])
(unpair-and-delete [this args])
(import-keys [this args])
(get-keys [this args])
(sign [this args])
(sign-typed-data [this args]))
+365
View File
@@ -0,0 +1,365 @@
(ns keycard.real-keycard
(:require
["react-native" :as rn]
["react-native-status-keycard" :default status-keycard]
[keycard.keycard :as keycard]
[react-native.platform :as platform]
[taoensso.timbre :as log]
[utils.address :as address]))
(defonce event-emitter
(if platform/ios?
(new (.-NativeEventEmitter rn) status-keycard)
(.-DeviceEventEmitter rn)))
(defonce active-listeners (atom []))
(defn start-nfc
[{:keys [on-success on-failure prompt-message]}]
(log/debug "start-nfc")
(.. status-keycard
(startNFC (str prompt-message))
(then on-success)
(catch on-failure)))
(defn stop-nfc
[{:keys [on-success on-failure error-message]}]
(log/debug "stop-nfc")
(.. status-keycard
(stopNFC (str error-message))
(then on-success)
(catch on-failure)))
(defn set-nfc-message
[{:keys [on-success on-failure status-message]}]
(log/debug "set-nfc-message")
(.. status-keycard
(setNFCMessage (str status-message))
(then on-success)
(catch on-failure)))
(defn check-nfc-support
[{:keys [on-success]}]
(.. status-keycard
nfcIsSupported
(then on-success)))
(defn check-nfc-enabled
[{:keys [on-success]}]
(.. status-keycard
nfcIsEnabled
(then on-success)))
(defn open-nfc-settings
[]
(.openNfcSettings status-keycard))
(defn remove-event-listeners
[]
(doseq [event ["keyCardOnConnected" "keyCardOnDisconnected" "keyCardOnNFCUserCancelled"
"keyCardOnNFCTimeout"]]
(.removeAllListeners ^js event-emitter event)))
(defn remove-event-listener
[^js event]
(.remove event))
(defn on-card-connected
[callback]
(.addListener ^js event-emitter "keyCardOnConnected" callback))
(defn on-card-disconnected
[callback]
(.addListener ^js event-emitter "keyCardOnDisconnected" callback))
(defn on-nfc-user-cancelled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCUserCancelled" callback))
(defn on-nfc-timeout
[callback]
(.addListener ^js event-emitter "keyCardOnNFCTimeout" callback))
(defn on-nfc-enabled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCEnabled" callback))
(defn on-nfc-disabled
[callback]
(.addListener ^js event-emitter "keyCardOnNFCDisabled" callback))
(defn set-pairings
[{:keys [pairings]}]
(.. status-keycard (setPairings (clj->js (or pairings {})))))
(defn register-card-events
[args]
(doseq [listener @active-listeners]
(remove-event-listener listener))
(reset! active-listeners
[(on-card-connected (:on-card-connected args))
(on-card-disconnected (:on-card-disconnected args))
(on-nfc-user-cancelled (:on-nfc-user-cancelled args))
(on-nfc-timeout (:on-nfc-timeout args))
(on-nfc-enabled (:on-nfc-enabled args))
(on-nfc-disabled (:on-nfc-disabled args))]))
(defn get-application-info
[{:keys [on-success on-failure]}]
(.. status-keycard
(getApplicationInfo)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(catch on-failure)))
(defn factory-reset
[{:keys [on-success on-failure]}]
(.. status-keycard
(factoryReset)
(then (fn [response]
(let [info (-> response
(js->clj :keywordize-keys true)
(update :key-uid address/normalized-hex))]
(on-success info))))
(catch on-failure)))
(defn install-applet
[{:keys [on-success on-failure]}]
(.. status-keycard
installApplet
(then on-success)
(catch on-failure)))
(defn install-cash-applet
[{:keys [on-success on-failure]}]
(.. status-keycard
installCashApplet
(then on-success)
(catch on-failure)))
(defn init-card
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(init pin)
(then on-success)
(catch on-failure)))
(defn install-applet-and-init-card
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(installAppletAndInitCard pin)
(then on-success)
(catch on-failure)))
(defn pair
[{:keys [password on-success on-failure]}]
(when password
(.. status-keycard
(pair password)
(then on-success)
(catch on-failure))))
(defn generate-and-load-key
[{:keys [mnemonic pin on-success on-failure]}]
(.. status-keycard
(generateAndLoadKey mnemonic pin)
(then on-success)
(catch on-failure)))
(defn unblock-pin
[{:keys [puk new-pin on-success on-failure]}]
(when (and new-pin puk)
(.. status-keycard
(unblockPin puk new-pin)
(then on-success)
(catch on-failure))))
(defn verify-pin
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(verifyPin pin)
(then on-success)
(catch on-failure))))
(defn change-pin
[{:keys [current-pin new-pin on-success on-failure]}]
(when (and current-pin new-pin)
(.. status-keycard
(changePin current-pin new-pin)
(then on-success)
(catch on-failure))))
(defn change-puk
[{:keys [pin puk on-success on-failure]}]
(when (and pin puk)
(.. status-keycard
(changePUK pin puk)
(then on-success)
(catch on-failure))))
(defn change-pairing
[{:keys [pin pairing on-success on-failure]}]
(when (and pin pairing)
(.. status-keycard
(changePairingPassword pin pairing)
(then on-success)
(catch on-failure))))
(defn unpair
[{:keys [pin on-success on-failure]}]
(when pin
(.. status-keycard
(unpair pin)
(then on-success)
(catch on-failure))))
(defn delete
[{:keys [on-success on-failure]}]
(.. status-keycard
(delete)
(then on-success)
(catch on-failure)))
(defn remove-key
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(removeKey pin)
(then on-success)
(catch on-failure)))
(defn remove-key-with-unpair
[{:keys [pin on-success on-failure]}]
(.. status-keycard
(removeKeyWithUnpair pin)
(then on-success)
(catch on-failure)))
(defn export-key
[{:keys [pin path on-success on-failure]}]
(.. status-keycard
(exportKeyWithPath pin path)
(then on-success)
(catch on-failure)))
(defn unpair-and-delete
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(unpairAndDelete pin)
(then on-success)
(catch on-failure))))
(defn import-keys
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(importKeys pin)
(then on-success)
(catch on-failure))))
(defn get-keys
[{:keys [pin on-success on-failure]}]
(when (not-empty pin)
(.. status-keycard
(getKeys pin)
(then on-success)
(catch on-failure))))
(defn sign
[{pin :pin path :path card-hash :hash on-success :on-success on-failure :on-failure}]
(when (and pin card-hash)
(if path
(.. status-keycard
(signWithPath pin path card-hash)
(then on-success)
(catch on-failure))
(.. status-keycard
(sign pin card-hash)
(then on-success)
(catch on-failure)))))
(defn sign-typed-data
[{card-hash :hash on-success :on-success on-failure :on-failure}]
(when card-hash
(.. status-keycard
(signPinless card-hash)
(then on-success)
(catch on-failure))))
(defrecord RealKeycard []
keycard/Keycard
(keycard/start-nfc [_this args]
(start-nfc args))
(keycard/stop-nfc [_this args]
(stop-nfc args))
(keycard/set-nfc-message [_this args]
(set-nfc-message args))
(keycard/check-nfc-support [_this args]
(check-nfc-support args))
(keycard/check-nfc-enabled [_this args]
(check-nfc-enabled args))
(keycard/open-nfc-settings [_this]
(open-nfc-settings))
(keycard/register-card-events [_this args]
(register-card-events args))
(keycard/on-card-connected [_this callback]
(on-card-connected callback))
(keycard/on-card-disconnected [_this callback]
(on-card-disconnected callback))
(keycard/remove-event-listener [_this event]
(remove-event-listener event))
(keycard/remove-event-listeners [_this]
(remove-event-listeners))
(keycard/set-pairings [_this args]
(set-pairings args))
(keycard/get-application-info [_this args]
(get-application-info args))
(keycard/factory-reset [_this args]
(factory-reset args))
(keycard/install-applet [_this args]
(install-applet args))
(keycard/install-cash-applet [_this args]
(install-cash-applet args))
(keycard/init-card [_this args]
(init-card args))
(keycard/install-applet-and-init-card [_this args]
(install-applet-and-init-card args))
(keycard/pair [_this args]
(pair args))
(keycard/generate-and-load-key [_this args]
(generate-and-load-key args))
(keycard/unblock-pin [_this args]
(unblock-pin args))
(keycard/verify-pin [_this args]
(verify-pin args))
(keycard/change-pin [_this args]
(change-pin args))
(keycard/change-puk [_this args]
(change-puk args))
(keycard/change-pairing [_this args]
(change-pairing args))
(keycard/unpair [_this args]
(unpair args))
(keycard/delete [_this args]
(delete args))
(keycard/remove-key [_this args]
(remove-key args))
(keycard/remove-key-with-unpair [_this args]
(remove-key-with-unpair args))
(keycard/export-key [_this args]
(export-key args))
(keycard/unpair-and-delete [_this args]
(unpair-and-delete args))
(keycard/import-keys [_this args]
(import-keys args))
(keycard/get-keys [_this args]
(get-keys args))
(keycard/sign [_this args]
(sign args))
(keycard/sign-typed-data [_this args]
(sign-typed-data args)))
+1 -3
View File
@@ -38,12 +38,10 @@
:always
(update :contacts conj (:id member))))
(defn community-chat-id->channel-id [chat-id] (subs chat-id constants/community-id-length))
(defn decode-chat-id
[chat-id]
(let [community-id (subs chat-id 0 constants/community-id-length)
channel-id (community-chat-id->channel-id chat-id)]
channel-id (subs chat-id constants/community-id-length)]
{:community-id community-id
:channel-id channel-id}))
+4 -3
View File
@@ -26,6 +26,7 @@
legacy.status-im.ui.components.invite.events
[legacy.status-im.ui.components.react :as react]
legacy.status-im.ui.screens.notifications-settings.events
legacy.status-im.ui.screens.privacy-and-security-settings.events
[legacy.status-im.utils.dimensions :as dimensions]
legacy.status-im.utils.logging.core
[legacy.status-im.utils.utils :as utils]
@@ -107,7 +108,8 @@
(when (and (multiaccounts.model/logged-in? db)
(= current-theme-type status-im.constants/theme-type-system))
{:profile.settings/switch-theme-fx
[(get-in db [:profile/profile :appearance]) (:view-id db)]})))
[(get-in db [:profile/profile :appearance])
(:view-id db) true]})))
(defn- on-biometric-auth-fail
[{:keys [code]}]
@@ -133,8 +135,7 @@
(>= (- now app-in-background-since)
constants/ms-in-bg-for-require-bioauth))]
(rf/merge cofx
{:db (dissoc db :app-in-background-since)
:effects.biometric/get-supported-type nil}
{:db (dissoc db :app-in-background-since)}
(mailserver/process-next-messages-request)
(when-not new-account?
(universal-links/process-stored-event))
@@ -28,7 +28,7 @@
[{:keys [db] :as cofx} {:keys [auth-method logout?]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
(rf/merge cofx
{:dispatch [:init-root :progress]
{:set-root :progress
:effects.shell/reset-state nil
:hide-popover nil
::logout nil
@@ -120,3 +120,12 @@
{:events [:multiaccounts.ui/switch-backup-enabled]}
[cofx enabled?]
(multiaccount-update cofx :backup-enabled? enabled? {}))
(rf/defn toggle-opensea-nfts-visibility
{:events [::toggle-opensea-nfts-visiblity]}
[cofx visible?]
(rf/merge cofx
{:db (assoc-in (:db cofx) [:profile/profile :opensea-enabled?] visible?)
;; need to add fully qualified namespace to counter circular deps
:dispatch [:legacy.status-im.wallet.core/fetch-collectibles-collection]}
(multiaccount-update :opensea-enabled? visible? {})))
+1 -1
View File
@@ -17,7 +17,7 @@
(reg-root-key-sub :ui/search :ui/search)
(reg-root-key-sub :network/type :network/type)
(reg-root-key-sub :network-status :network-status)
(reg-root-key-sub :peer-stats/count :peer-stats/count)
(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)
@@ -1,9 +1,14 @@
(ns legacy.status-im.ui.components.connectivity.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.animation :as animation]
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.react :as react])
(:require-macros [legacy.status-im.utils.views :as views]))
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[utils.i18n :as i18n])
(:require-macros [legacy.status-im.utils.views :as views :refer [defview letsubs]]))
(defn easing
[direction n]
@@ -67,3 +72,112 @@
colors/white)
:left
(* 0.15 parent-width))}]]]))
(defview loading-indicator
[]
(letsubs [fetching? [:mailserver/fetching?]
window-width [:dimensions/window-width]]
(when fetching?
[loading-indicator-anim window-width])))
(defn hide-sheet-and-dispatch
[event]
(re-frame/dispatch [:bottom-sheet/hide-old])
(re-frame/dispatch event))
(defview connectivity-sheet
[]
(letsubs [{:keys [peers node mobile sync]} [:connectivity/state]
current-mailserver-name [:mailserver/current-name]
peers-count [:peers-count]
{:keys [syncing-on-mobile-network?]} [:profile/profile]]
[:<>
[quo/header {:title (i18n/label :t/connection-status) :border-bottom false}]
[quo/list-header (i18n/label :t/peer-to-peer)]
(if (= peers :offline)
[list.item/list-item
{:title (i18n/label :t/not-connected-to-peers)
:accessibility-label "not-connected-to-peers"
:subtitle (i18n/label :t/unable-to-send-messages)
:subtitle-max-lines 2
:theme :negative
:icon :main-icons/network}]
[list.item/list-item
{:title (str (i18n/label :t/connected-to)
" " peers-count
" " (string/lower-case (i18n/label :t/peers)))
:accessibility-label "connected-to-n-peers"
:subtitle (i18n/label :t/can-send-messages)
:subtitle-max-lines 2
:theme :positive
:icon :main-icons/network}])
[quo/list-header (i18n/label :t/history-nodes)]
(cond
(#{:error :offline} node)
[list.item/list-item
{:title (i18n/label :t/not-connected-nodes)
:accessibility-label "not-connected-nodes"
:subtitle (i18n/label :t/unable-to-fetch)
:theme :negative
:icon :main-icons/mailserver}]
(= node :disabled)
[list.item/list-item
{:title (i18n/label :t/nodes-disabled)
:accessibility-label "nodes-disabled"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(and mobile (not sync))
[list.item/list-item
{:title (i18n/label :t/waiting-wi-fi)
:accessibility-label "waiting-wi-fi"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(= node :connecting)
[list.item/list-item
{:title (i18n/label :t/connecting)
:accessibility-label "connecting"
:subtitle (i18n/label :t/unable-to-fetch)
:icon :main-icons/mailserver}]
(= node :online)
[list.item/list-item
{:title (str (i18n/label :t/connected-to) " " current-mailserver-name)
:accessibility-label "connected-to-mailserver"
:subtitle (i18n/label :t/you-can-fetch)
:theme :positive
:icon :main-icons/mailserver}])
[list.item/list-item
{:title (i18n/label :t/settings)
:accessibility-label "settings"
:theme :accent
:on-press #(hide-sheet-and-dispatch [:navigate-to :legacy-sync-settings])
:icon :main-icons/settings}]
(when mobile
[:<>
[react/view
{:margin-vertical 8
:background-color colors/gray-lighter
:height 36
:align-items :center
:justify-content :center}
[react/text {:style {:color colors/gray}} (i18n/label :t/youre-on-mobile-network)]]
[list.item/list-item
{:title (i18n/label :t/mobile-network-use-mobile)
:accessibility-label "mobile-network-use-mobile"
:accessory :switch
:on-press #(re-frame/dispatch [:mobile-network/set-syncing
(not syncing-on-mobile-network?)])
:active syncing-on-mobile-network?}]
[react/text {:style {:margin-horizontal 16 :margin-bottom 12 :color colors/gray}}
(i18n/label :t/status-mobile-descr)]])]))
(defn get-icon
[{:keys [peers node mobile sync]}]
(if (or (= peers :offline)
(= node :offline)
(= node :connecting))
:main-icons/offline
(if mobile
(if sync :main-icons/mobile-sync :main-icons/mobile-sync-off)
(when (#{:error :disabled} node) :main-icons/node-offline))))
@@ -18,7 +18,6 @@
[{:keys [current-log-level
telemetry-enabled?
light-client-enabled?
store-confirmations-enabled?
current-fleet
test-networks-enabled?
is-goerli-enabled?
@@ -78,15 +77,6 @@
[:wakuv2.ui/toggle-light-client (not light-client-enabled?)])
:accessory :switch
:active light-client-enabled?}
{:size :small
:title (i18n/label :t/store-confirmations)
:accessibility-label :store-confirmations
:container-margin-bottom 8
:on-press
#(re-frame/dispatch
[:wakuv2.ui/toggle-store-confirmations (not store-confirmations-enabled?)])
:accessory :switch
:active store-confirmations-enabled?}
{:size :small
:title "Testnet mode"
:accessibility-label :test-networks-enabled
@@ -124,14 +114,13 @@
(views/defview advanced-settings
[]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
store-confirmations-enabled? [:profile/store-confirmations-enabled?]
telemetry-enabled? [:profile/telemetry-enabled?]
current-log-level [:log-level/current-log-level]
current-fleet [:fleets/current-fleet]
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
telemetry-enabled? [:profile/telemetry-enabled?]
current-log-level [:log-level/current-log-level]
current-fleet [:fleets/current-fleet]
peer-syncing-enabled? [:profile/peer-syncing-enabled?]]
[:<>
[quo/page-nav
{:type :title
@@ -141,14 +130,13 @@
:on-press #(rf/dispatch [:navigate-back])}]
[list/flat-list
{:data (flat-list-data
{:current-log-level current-log-level
:telemetry-enabled? telemetry-enabled?
:light-client-enabled? light-client-enabled?
:store-confirmations-enabled? store-confirmations-enabled?
:current-fleet current-fleet
:dev-mode? false
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
{:current-log-level current-log-level
:telemetry-enabled? telemetry-enabled?
:light-client-enabled? light-client-enabled?
:current-fleet current-fleet
:dev-mode? false
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
:key-fn (fn [_ i] (str i))
:render-fn render-item}]]))
@@ -0,0 +1,11 @@
(ns legacy.status-im.ui.screens.dapps-permissions.styles
(:require
[legacy.status-im.ui.components.colors :as colors]))
(def icon-container
{:width 40
:height 40
:border-radius 20
:background-color colors/gray-lighter
:align-items :center
:justify-content :center})
@@ -0,0 +1,64 @@
(ns legacy.status-im.ui.screens.dapps-permissions.views
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.icons.icons :as icons]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.components.topbar :as topbar]
[legacy.status-im.ui.screens.dapps-permissions.styles :as styles]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
(defn d-icon
[]
[react/view styles/icon-container
[icons/icon :main-icons/dapp {:color colors/gray}]])
(defn prepare-items
[{:keys [dapp permissions]}]
{:title dapp
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :manage-dapps-permissions
{:dapp dapp :permissions permissions}])
:icon [d-icon]})
(defn prepare-items-manage
[name]
(fn [permission]
{:title (cond
(= permission constants/dapp-permission-web3)
name
(= permission constants/dapp-permission-contact-code)
(i18n/label :t/contact-code))
:size :small
:accessory [icons/icon :main-icons/check {}]}))
(views/defview dapps-permissions
[]
(views/letsubs [permissions [:dapps/permissions]]
[list/flat-list
{:data (vec (map prepare-items (vals permissions)))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item}]))
(views/defview manage
[]
(views/letsubs [{:keys [dapp permissions]} [:get-screen-params]
{:keys [name]} [:dapps-account]]
[:<>
[topbar/topbar {:title dapp}]
[list/flat-list
{:data (vec (map (prepare-items-manage name) permissions))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item}]
[react/view
{:padding-vertical 16
:padding-horizontal 16}
[quo/button
{:theme :negative
:on-press #(re-frame/dispatch [:dapps/revoke-access dapp])}
(i18n/label :t/revoke-access)]]]))
@@ -0,0 +1,13 @@
(ns legacy.status-im.ui.screens.link-previews-settings.styles)
(def link-preview-settings-image
{:height 100
:align-self :center
:margin-top 16})
(def whitelist-container
{:flex-direction :row
:justify-content :space-between})
(def enable-all
{:align-self :flex-end})
@@ -0,0 +1,67 @@
(ns legacy.status-im.ui.screens.link-previews-settings.views
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.react-native.resources :as resources]
[legacy.status-im.ui.components.core :as components]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.link-previews-settings.styles :as styles]
[quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.contexts.chat.messenger.messages.link-preview.events]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn prepare-urls-items-data
[link-previews-enabled-sites]
(fn [{:keys [title address]}]
(let [enabled? (contains? link-previews-enabled-sites title)]
{:title title
:subtitle address
:size :small
:accessory :switch
:active (contains? link-previews-enabled-sites title)
:on-press #(re-frame/dispatch
[:chat.ui/enable-link-previews title ((complement boolean) enabled?)])})))
(views/defview link-previews-settings
[]
(views/letsubs [link-previews-whitelist [:link-previews-whitelist]
link-previews-enabled-sites [:link-preview/enabled-sites]]
(let [all-enabled (= (count link-previews-whitelist) (count link-previews-enabled-sites))]
[:<>
[quo/page-nav
{:type :title
:title (i18n/label :t/chat-link-previews)
:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
[react/image
{:source (resources/get-theme-image :unfurl)
:style styles/link-preview-settings-image}]
[components/text {:style {:margin 16}}
(i18n/label :t/you-can-choose-preview-websites)]
[components/separator {:style {:margin-vertical 8}}]
[react/view styles/whitelist-container
[components/list-header (i18n/label :t/websites)]
(when (> (count link-previews-whitelist) 1)
[components/button
{:on-press #(re-frame/dispatch [:chat.ui/enable-all-link-previews
link-previews-whitelist
(not all-enabled)])
:type :secondary
:style styles/enable-all}
(if all-enabled
(i18n/label :t/disable-all)
(i18n/label :t/enable-all))])]
[list/flat-list
{:data (vec (map (prepare-urls-items-data link-previews-enabled-sites)
link-previews-whitelist))
:key-fn (fn [_ i] (str i))
:render-fn list.item/list-item
:footer [quo/text
{:color :secondary
:style {:margin 16}} (i18n/label :t/previewing-may-share-metadata)]}]])))
@@ -1,24 +1,17 @@
(ns legacy.status-im.ui.screens.peers-stats
(:require
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.core :as react-native.core]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.re-frame :as re-frame]))
(defn peers-stats
[]
(let [peers-count (rf/sub [:peer-stats/count])
theme (rf/sub [:theme])]
(rn/use-mount
(fn []
(rf/dispatch [:peer-stats/get-count])))
[rn/view
{:style {:flex 1
:margin-horizontal 8}}
[rn/view
(let [peers-count (re-frame/sub [:peers-count])]
[react-native.core/view
{:flex 1
:margin-horizontal 8}
[react-native.core/view
{:style {:flex-direction :row
:margin-vertical 8
:justify-content :space-between}}
[rn/text {:style {:color (colors/theme-colors colors/neutral-100 colors/white theme)}}
(str (i18n/label :t/peers-count) ": " peers-count)]]]))
[react-native.core/text (str (i18n/label :t/peers-count) ": " peers-count)]]]))
@@ -0,0 +1,81 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile
(:require
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.privacy-and-security-settings.events :as delete-profile]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.security.core :as security]))
(defn valid-password?
[password]
(>= (count password) 6))
(defn on-delete-profile
[password]
#(do
(re-frame/dispatch
[::delete-profile/delete-profile @password])
(reset! password nil)))
(defn delete-profile
[]
(let [password (reagent/atom nil)
text-input-ref (atom nil)]
(fn []
(let [profile @(re-frame/subscribe [:profile/profile])
error @(re-frame/subscribe [:delete-profile/error])
keep-keys-on-keycard? @(re-frame/subscribe
[:delete-profile/keep-keys-on-keycard?])]
(when (and @text-input-ref error (not @password))
(.clear ^js @text-input-ref))
[react/keyboard-avoiding-view {:style {:flex 1}}
[react/scroll-view {:style {:flex 1}}
[react/view {:style {:align-items :center}}
[quo/text
{:weight :bold
:size :x-large}
(i18n/label :t/delete-profile)]]
[list.item/list-item
{:title (profile.utils/displayed-name profile)
:icon [chat-icon.screen/contact-icon-contacts-tab profile]}]
[quo/text
{:style {:margin-horizontal 24}
:align :center
:color :negative}
(i18n/label :t/delete-profile-warning)]
[quo/text-input
{:style {:margin-horizontal 36
:margin-top 36}
:show-cancel false
:secure-text-entry true
:return-key-type :next
:on-submit-editing nil
:auto-focus true
:on-change-text #(reset! password (security/mask-data %))
:bottom-value 36
:get-ref #(reset! text-input-ref %)
:error (when (and error (not @password))
(if (= :wrong-password error)
(i18n/label :t/wrong-password)
(str error)))}]]
[react/view {:style {:align-items :center}}
[quo/separator]
(when (not keep-keys-on-keycard?)
[quo/text
{:style {:margin-horizontal 24 :margin-bottom 16}
:align :center
:color :negative}
(i18n/label :t/delete-profile-warning)])
[react/view
{:style {:margin-vertical 8}}
[quo/button
{:on-press (on-delete-profile password)
:theme :negative
:accessibility-label :delete-profile-confirm
:disabled ((complement valid-password?) @password)}
(i18n/label :t/delete-profile)]]]]))))
@@ -0,0 +1,73 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.events
(:require
[clojure.string :as string]
[legacy.status-im.utils.deprecated-types :as types]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(defn safe-blank?
[s]
(or (not s)
(string/blank? s)))
(re-frame/reg-fx
::delete-profile
(fn [{:keys [address key-uid callback masked-password]}]
(let [hashed-password
(-> masked-password
security/safe-unmask-data
native-module/sha3)]
(native-module/verify
address
hashed-password
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(log/info "[delete-profile] verify-password" result error)
(if-not (safe-blank? error)
(callback :wrong-password nil)
(native-module/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(callback error nil)))))))))))
(rf/defn delete-profile
{:events [::delete-profile]}
[{:keys [db] :as cofx} masked-password]
(log/info "[delete-profile] delete")
(let [{:keys [key-uid wallet-root-address]} (:profile/profile db)]
{:db (dissoc db :delete-profile/error)
::delete-profile
{:masked-password masked-password
:key-uid key-uid
:address wallet-root-address
:callback
(fn [error result]
(log/info "[delete-profile] callback" error)
(if (safe-blank? error)
(re-frame/dispatch [::on-delete-profile-success result])
(re-frame/dispatch [::on-delete-profile-failure error])))}}))
(rf/defn on-delete-profile-success
{:events [::on-delete-profile-success]}
[cofx]
(log/info "[delete-profile] on-success")
{:effects.utils/show-popup
{:title (i18n/label :t/profile-deleted-title)
:content (i18n/label :t/profile-deleted-content)
:on-dismiss #(re-frame/dispatch [:logout])}})
(rf/defn on-delete-profile-failure
{:events [::on-delete-profile-failure]}
[{:keys [db]} error]
(log/info "[delete-profile] on-failure" error)
{:db (assoc db :delete-profile/error error)})
(rf/defn keep-keys-on-keycard
{:events [::keep-keys-on-keycard]}
[{:keys [db] :as cofx} checked?]
{:db (assoc-in db [:delete-profile/keep-keys-on-keycard?] checked?)})
@@ -0,0 +1,34 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(rf/defn handle-messages-from-contacts-only-switched
{:events [::messages-from-contacts-only-switched]}
[cofx value]
(multiaccounts.update/multiaccount-update cofx
:messages-from-contacts-only
value
{}))
(views/defview messages-from-contacts-only-view
[]
(views/letsubs [{:keys [messages-from-contacts-only]} [:profile/profile]]
[react/view {:margin-top 8}
[list.item/list-item
{:active (not messages-from-contacts-only)
:accessory :radio
:title (i18n/label :t/anyone)
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched false])}]
[list.item/list-item
{:active messages-from-contacts-only
:accessory :radio
:title (i18n/label :t/contacts)
:subtitle (i18n/label :t/messages-from-contacts-only-subtitle)
:subtitle-max-lines 4
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched true])}]]))
@@ -0,0 +1,175 @@
(ns legacy.status-im.ui.screens.privacy-and-security-settings.views
(:require
[legacy.status-im.multiaccounts.reset-password.core :as reset-password]
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.ui.components.core :as components]
[legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[quo.core :as quo]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.config :as config]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf])
(:require-macros [legacy.status-im.utils.views :as views]))
(defn separator
[]
[components/separator {:style {:margin-vertical 8}}])
(def titles
{constants/profile-pictures-visibility-contacts-only (i18n/label :t/recent-recipients)
constants/profile-pictures-visibility-everyone (i18n/label :t/everyone)
constants/profile-pictures-visibility-none (i18n/label :t/none)
constants/profile-pictures-show-to-contacts-only (i18n/label :t/recent-recipients)
constants/profile-pictures-show-to-everyone (i18n/label :t/everyone)
constants/profile-pictures-show-to-none (i18n/label :t/none)})
(views/defview privacy-and-security
[]
(views/letsubs [{:keys [preview-privacy?
messages-from-contacts-only
webview-allow-permission-requests?
opensea-enabled?
profile-pictures-visibility]}
[:profile/profile]
has-picture [:profile/has-picture]
profile-pictures-show-to [:multiaccount/profile-pictures-show-to]]
[:<>
[quo/page-nav
{:type :no-title
:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}]
[react/scroll-view {:padding-vertical 8}
[components/list-header (i18n/label :t/privacy)]
[list.item/list-item
{:size :small
:title (i18n/label :t/set-dapp-access-permissions)
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
:accessibility-label :dapps-permissions-button
:chevron true}]
[list.item/list-item
{:size :small
:title (if platform/android?
(i18n/label :t/hide-content-when-switching-apps)
(i18n/label :t/hide-content-when-switching-apps-ios))
:container-margin-bottom 8
:active preview-privacy?
:accessory :switch
:on-press #(re-frame/dispatch
[:profile.settings/change-preview-privacy
((complement boolean) preview-privacy?)])}]
(when config/collectibles-enabled?
[list.item/list-item
{:size :small
:title (i18n/label :t/display-collectibles)
:container-margin-bottom 8
:active opensea-enabled?
:accessory :switch
:on-press #(re-frame/dispatch
[::multiaccounts.update/toggle-opensea-nfts-visiblity
(not opensea-enabled?)])}])
[list.item/list-item
{:size :small
:title (i18n/label :t/chat-link-previews)
:chevron true
:on-press #(re-frame/dispatch [:open-modal :legacy-link-previews-settings])
:accessibility-label :chat-link-previews}]
[list.item/list-item
{:size :small
:title (i18n/label :t/accept-new-chats-from)
:chevron true
:accessory :text
:accessory-text (i18n/label (if messages-from-contacts-only
:t/contacts
:t/anyone))
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
:accessibility-label :accept-new-chats-from}]
[list.item/list-item
{:size :small
:title (i18n/label :t/reset-password)
:chevron true
:accessory :text
:on-press #(do
(re-frame/dispatch [::reset-password/clear-form-vals])
(re-frame/dispatch [:navigate-to :reset-password]))
:accessibility-label :reset-password}]
(when platform/android?
[list.item/list-item
{:size :small
:title (i18n/label :t/webview-camera-permission-requests)
:active webview-allow-permission-requests?
:accessory :switch
:subtitle (i18n/label :t/webview-camera-permission-requests-subtitle)
:subtitle-max-lines 2
:on-press #(re-frame/dispatch
[:profile.settings/profile-update
:webview-allow-permission-requests?
((complement boolean) webview-allow-permission-requests?)])}])
[separator]
[components/list-header (i18n/label :t/privacy-photos)]
[list.item/list-item
{:size :small
:title (i18n/label :t/show-profile-pictures)
:accessibility-label :show-profile-pictures
:accessory :text
:accessory-text (get titles profile-pictures-visibility)
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security-profile-pic])
:chevron true}]
[list.item/list-item
{:size :small
:title (i18n/label :t/show-profile-pictures-to)
:disabled (not has-picture)
:accessibility-label :show-profile-pictures-to
:accessory :text
:accessory-text (get titles profile-pictures-show-to)
:on-press #(re-frame/dispatch [:navigate-to
:privacy-and-security-profile-pic-show-to])
:chevron true}]
[separator]
[list.item/list-item
{:size :small
:theme :negative
:title (i18n/label :t/delete-my-profile)
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
:accessibility-label :dapps-permissions-button
:chevron true}]]]))
(defn ppst-radio-item
[id value]
[list.item/list-item
{:active (= value id)
:accessory :radio
:title (get titles id)
:on-press #(re-frame/dispatch [:profile.settings/change-profile-pictures-show-to id])}])
(views/defview profile-pic-show-to
[]
(views/letsubs [{:keys [profile-pictures-show-to]} [:profile/profile]]
[react/view {:margin-top 8}
[ppst-radio-item constants/profile-pictures-show-to-everyone profile-pictures-show-to]
[ppst-radio-item constants/profile-pictures-show-to-contacts-only profile-pictures-show-to]
[ppst-radio-item constants/profile-pictures-show-to-none profile-pictures-show-to]
[react/view {:style {:margin-horizontal 16}}
[components/text {:color :secondary}
(i18n/label :t/privacy-show-to-warning)]]]))
(defn ppvf-radio-item
[id value]
[list.item/list-item
{:active (= value id)
:accessory :radio
:title (get titles id)
:on-press #(re-frame/dispatch [:profile.settings/profile-update :profile-pictures-visibility id])}])
(views/defview profile-pic
[]
(views/letsubs [{:keys [profile-pictures-visibility]} [:profile/profile]]
[react/view {:margin-top 8}
[ppvf-radio-item constants/profile-pictures-visibility-everyone profile-pictures-visibility]
[ppvf-radio-item constants/profile-pictures-visibility-contacts-only profile-pictures-visibility]
[ppvf-radio-item constants/profile-pictures-visibility-none profile-pictures-visibility]]))
@@ -13,6 +13,12 @@
[]
[rn/scroll-view {:flex 1}
[components/list-header "Legacy settings"]
[list.item/list-item
{:icon :main-icons/security
:title (i18n/label :t/privacy-and-security)
:accessibility-label :privacy-and-security-settings-button
:chevron true
:on-press #(re-frame/dispatch [:open-modal :legacy-privacy-and-security])}]
[list.item/list-item
{:icon :main-icons/mobile
:title (i18n/label :t/sync-settings)
+40 -2
View File
@@ -8,10 +8,12 @@
[legacy.status-im.ui.screens.bug-report :as bug-report]
[legacy.status-im.ui.screens.communities.invite :as communities.invite]
[legacy.status-im.ui.screens.communities.members :as members]
[legacy.status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
[legacy.status-im.ui.screens.default-sync-period-settings.view :as default-sync-period-settings]
[legacy.status-im.ui.screens.fleet-settings.views :as fleet-settings]
[legacy.status-im.ui.screens.glossary.view :as glossary]
[legacy.status-im.ui.screens.help-center.views :as help-center]
[legacy.status-im.ui.screens.link-previews-settings.views :as link-previews-settings]
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
[legacy.status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
@@ -19,6 +21,10 @@
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
[legacy.status-im.ui.screens.pairing.views :as pairing]
[legacy.status-im.ui.screens.peers-stats :as peers-stats]
[legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile]
[legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only :as
messages-from-contacts-only]
[legacy.status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security]
[legacy.status-im.ui.screens.profile.seed.views :as profile.seed]
[legacy.status-im.ui.screens.profile.user.views :as profile.user]
[legacy.status-im.ui.screens.progress.views :as progress]
@@ -47,8 +53,7 @@
[]
[;;PROGRESS
{:name :progress
:options {:insets {:top? true}
:theme :dark}
:options {:insets {:top? true}}
:component progress/progress}
;;COMMUNITY
@@ -88,6 +93,17 @@
:insets {:top? platform/android?}}
:component profile.user/legacy-settings}
;; PRIVACY AND SECURITY
{:name :legacy-privacy-and-security
:options {:topBar {:visible false}
:insets {:top? platform/android?}}
:component privacy-and-security/privacy-and-security}
{:name :legacy-link-previews-settings
:options {:topBar {:visible false}
:insets {:top? platform/android?}}
:component link-previews-settings/link-previews-settings}
;; SYNC
{:name :legacy-sync-settings
:options {:topBar {:visible false}
@@ -133,6 +149,25 @@
{:name :edit-mailserver
:options {:insets {:top? true}}
:component edit-mailserver/edit-mailserver}
{:name :dapps-permissions
:options {:topBar (topbar-options :t/dapps-permissions)
:insets {:top? true}}
:component dapps-permissions/dapps-permissions}
{:name :messages-from-contacts-only
:options {:topBar (topbar-options :t/accept-new-chats-from)
:insets {:top? true}}
:component messages-from-contacts-only/messages-from-contacts-only-view}
{:name :privacy-and-security-profile-pic-show-to
:options {:topbar (topbar-options :t/show-profile-pictures-to)
:insets {:top? true}}
:component privacy-and-security/profile-pic-show-to}
{:name :privacy-and-security-profile-pic
:options {:topBar (topbar-options :t/show-profile-pictures)
:insets {:top? true}}
:component privacy-and-security/profile-pic}
{:name :manage-dapps-permissions
:options {:insets {:top? true}}
:component dapps-permissions/manage}
{:name :rpc-usage-info
:options {:topBar (topbar-options :t/rpc-usage-info)
:insets {:top? true}}
@@ -160,6 +195,9 @@
:options {:topBar (topbar-options :t/reset-password)
:insets {:top? true}}
:component reset-password/reset-password}
{:name :delete-profile
:insets {:bottom? true}
:component delete-profile/delete-profile}
{:name :default-sync-period-settings
:options {:topBar (topbar-options :t/default-sync-period)
:insets {:top? true}}
+16
View File
@@ -0,0 +1,16 @@
(ns legacy.status-im.utils.hex
(:require
[clojure.string :as string]))
(defn normalize-hex
[hex]
(when hex
(string/lower-case (if (string/starts-with? hex "0x")
(subs hex 2)
hex))))
(defn valid-hex?
[hex]
(let [hex (normalize-hex hex)]
(and (re-matches #"^[0-9a-fA-F]+$" hex)
(not= (js/parseInt hex 16) 0))))
@@ -0,0 +1,58 @@
(ns legacy.status-im.utils.keychain.core
(:require
[oops.core :as oops]
[re-frame.core :as re-frame]
[react-native.keychain :as keychain]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- whisper-key-name
[address]
(str address "-whisper"))
(re-frame/reg-fx
:keychain/get-keycard-keys
(fn [[key-uid callback]]
(keychain/get-credentials
key-uid
(fn [encryption-key-data]
(if encryption-key-data
(keychain/get-credentials
(whisper-key-name key-uid)
(fn [whisper-key-data]
(if whisper-key-data
(callback [(oops/oget encryption-key-data "password")
(oops/oget whisper-key-data "password")])
(callback nil))))
(callback nil))))))
(re-frame/reg-fx
:keychain/save-keycard-keys
(fn [[key-uid encryption-public-key whisper-private-key]]
(keychain/save-credentials
key-uid
key-uid
encryption-public-key
#(when-not %
(log/error
(str "Error while saving encryption-public-key"))))
(keychain/save-credentials
(whisper-key-name key-uid)
key-uid
whisper-private-key
#(when-not %
(log/error
(str "Error while saving whisper-private-key"))))))
(rf/defn get-keycard-keys
[_ key-uid]
{:keychain/get-keycard-keys
[key-uid
#(re-frame/dispatch
[:multiaccounts.login.callback/get-keycard-keys-success key-uid %])]})
(rf/defn save-keycard-keys
[_ key-uid encryption-public-key whisper-private-key]
{:keychain/save-keycard-keys [key-uid
encryption-public-key
whisper-private-key]})
@@ -128,6 +128,7 @@
:current-chat-id
:network
:network-status
:peers-count
:peers-summary
:sync-state
:view-id
+130
View File
@@ -0,0 +1,130 @@
(ns legacy.status-im.utils.test
(:require
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]))
(def native-status (js/require "../../modules/react-native-status/nodejs/bindings"))
(def fs (js/require "fs"))
(def path (js/require "path"))
(def os (js/require "os"))
(def tmpdir (.tmpdir os))
(def test-dir-prefix (.join path tmpdir "status-mobile-tests"))
(def test-dir (.mkdtempSync fs test-dir-prefix))
(def initialized? (atom false))
(defn signal-received-callback
[a]
(re-frame/dispatch [:signals/signal-received a]))
;; We poll for signals, could not get callback working
(defn init!
[]
(when-not @initialized?
(.setSignalEventCallback native-status)
(reset! initialized? true)
(js/setInterval (fn []
(.pollSignal native-status signal-received-callback)
100))))
(def ui-helper
(clj->js
{:clearCookies identity
:clearStorageAPIs identity}))
(def encryption-utils
(clj->js
{:sha3
(fn [s] (.sha3 native-status s))
:setBlankPreviewFlag
identity
:encodeTransfer
(fn [to-norm amount-hex]
(.encodeTransfer native-status to-norm amount-hex))
:hexToNumber
(fn [hex] (.hexToNumber native-status hex))
:decodeParameters
(fn [decode-param-json]
(.decodeParameters native-status decode-param-json))
:numberToHex
(fn [num-str] (.numberToHex native-status num-str))
:initKeystore
(fn [key-uid callback]
(callback (.initKeystore native-status
(str test-dir "/keystore/" key-uid))))
:multiformatDeserializePublicKey
(fn [public-key deserialization-key callback]
(callback (.multiformatDeserializePublicKey
native-status
public-key
deserialization-key)))}))
(def account-manager
(clj->js
{:openAccounts
(fn [callback]
(callback (.openAccounts native-status test-dir)))
:createAccountAndLogin
(fn [request] (.createAccountAndLogin native-status request))
:logout
(fn [] (.logout native-status))
:multiAccountImportMnemonic
(fn [json callback]
(callback (.multiAccountImportMnemonic native-status json)))
:multiAccountLoadAccount
(fn [json callback]
(callback (.multiAccountLoadAccount native-status json)))
:multiAccountDeriveAddresses
(fn [json callback]
(callback (.multiAccountDeriveAddresses native-status json)))
:multiAccountGenerateAndDeriveAddresses
(fn [json callback]
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
:multiAccountStoreDerived
(fn [json callback]
(callback (.multiAccountStoreDerivedAccounts native-status json)))}))
(def utils
(clj->js
{:backupDisabledDataDir
(fn [] (str test-dir "/backup"))
:keystoreDir (fn [] "")
:toChecksumAddress
(fn [address] (.toChecksumAddress native-status address))
:checkAddressChecksum
(fn [address] (.checkAddressChecksum native-status address))
:validateMnemonic
(fn [json callback] (callback (.validateMnemonic native-status json)))
:isAddress
(fn [address] (.isAddress native-status address))}))
(def log-manager
(clj->js
{:logFileDirectory
(fn [] (str test-dir "/log"))
:initLogging
(fn [enabled mobile-system log-level callback]
(callback (.initLogging native-status
(types/clj->json {:Enabled enabled
:MobileSystem mobile-system
:Level log-level
:File (str test-dir "/geth.log")}))))}))
(def network
(clj->js
{:callPrivateRPC
(fn [payload callback]
(callback (.callPrivateRPC native-status payload)))}))
(def status
(clj->js
{:getNodeConfig
(fn [] (types/clj->json {:WakuV2Config ""}))
:fleets
(fn [] (.fleets native-status))
:startLocalNotifications
identity}))
@@ -130,7 +130,7 @@
status-type]}]
(and
(= status-type constants/visibility-status-inactive)
(pos? (:peer-stats/count db)))
(> (:peers-count db) 0))
;; Disable broadcasting further updates
(conj {:ms 1000
:dispatch
-16
View File
@@ -137,19 +137,3 @@
:on-error #(log/error "failed to set light client"
{:error %
:enabled? enabled?})}]})
(rf/defn toggle-store-confirmations
{:events [:wakuv2.ui/toggle-store-confirmations]}
[{:keys [db]} enabled?]
{:db (assoc-in db
[:profile/profile :wakuv2-config :EnableStoreConfirmationForMessagesSent]
enabled?)
:json-rpc/call [{:method "wakuext_setStoreConfirmationForMessagesSent"
:params [{:enabled enabled?}]
:on-success (fn []
(log/info "store confirmation set successfully" enabled?)
(re-frame/dispatch [:logout]))
:on-error #(log/error "failed to set store confirmation"
{:error %
:enabled? enabled?})}]})
+2 -5
View File
@@ -110,11 +110,8 @@
(def status-keycard
#js
{:default #js
{:nfcIsSupported (fn [] #js {:then identity})
:nfcIsEnabled (fn [] #js {:then identity})
:getApplicationInfo (fn [] #js {:then identity})
:getKeys (fn [] #js {:then identity})
:setPairings (fn [] #js {:then identity})}})
{:nfcIsSupported (fn [] #js {:then identity})
:nfcIsEnabled (fn [] #js {:then identity})}})
(def snoopy #js {:default #js {}})
(def snoopy-filter #js {:default #js {}})
+100 -26
View File
@@ -72,12 +72,10 @@
(log/debug "[native-module] init-keystore" key-uid)
(.initKeystore ^js (encryption) key-uid callback))
(defn initialize-application
[request callback]
(log/debug "[native-module] initialize-application")
(.initializeApplication ^js (account-manager)
(types/clj->json request)
#(callback (types/json->clj %))))
(defn open-accounts
[callback]
(log/debug "[native-module] open-accounts")
(.openAccounts ^js (account-manager) #(callback (types/json->clj %))))
(defn prepare-dir-and-update-config
[key-uid config callback]
@@ -87,6 +85,31 @@
config
#(callback (types/json->clj %))))
(defn save-multiaccount-and-login-with-keycard
"NOTE: chat-key is a whisper private key sent from keycard"
[key-uid multiaccount-data password settings config accounts-data chat-key]
(log/debug "[native-module] save-account-and-login-with-keycard")
(init-keystore
key-uid
#(.saveAccountAndLoginWithKeycard
^js (account-manager)
multiaccount-data
password
settings
config
accounts-data
chat-key)))
(defn login-with-config
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password config]
(log/debug "[native-module] loginWithConfig")
(clear-web-data)
(let [config (if config (types/clj->json config) "")]
(init-keystore
key-uid
#(.loginWithConfig ^js (account-manager) account-data hashed-password config))))
(defn login-account
"NOTE: beware, the password has to be sha3 hashed"
[{:keys [keyUid] :as request}]
@@ -128,6 +151,19 @@
(clear-web-data)
(.logout ^js (account-manager)))
(defn multiaccount-load-account
"NOTE: beware, the password has to be sha3 hashed
this function is used after storing an account when you still want to
derive accounts from it, because saving an account flushes the loaded keys
from memory"
[address hashed-password callback]
(log/debug "[native-module] multiaccount-load-account")
(.multiAccountLoadAccount ^js (account-manager)
(types/clj->json {:address address
:password hashed-password})
callback))
(defn multiaccount-derive-addresses
"NOTE: this should be named derive-accounts
this only derive addresses, they still need to be stored
@@ -141,6 +177,38 @@
:paths paths})
callback)))
(defn multiaccount-store-account
"NOTE: beware, the password has to be sha3 hashed
this stores the account and flush keys in memory so
in order to also store derived accounts like initial wallet
and chat accounts, you need to load the account again with
`multiaccount-load-account` before using `multiaccount-store-derived`
and the id of the account stored will have changed"
[account-id key-uid hashed-password callback]
(log/debug "[native-module] multiaccount-store-account")
(when (status)
(init-keystore
key-uid
#(.multiAccountStoreAccount ^js (account-manager)
(types/clj->json {:accountID account-id
:password hashed-password})
callback))))
(defn multiaccount-store-derived
"NOTE: beware, the password has to be sha3 hashed"
[account-id key-uid paths hashed-password callback]
(log/debug "[native-module] multiaccount-store-derived"
"account-id"
account-id)
(init-keystore
key-uid
#(.multiAccountStoreDerived ^js (account-manager)
(types/clj->json {:accountID account-id
:paths paths
:password hashed-password})
callback)))
(defn multiaccount-generate-and-derive-addresses
"used to generate multiple multiaccounts for onboarding
NOTE: nothing is saved so you will need to use
@@ -164,12 +232,37 @@
:Bip39Passphrase password})
callback))
(defn multiaccount-import-private-key
[private-key callback]
(log/debug "[native-module] multiaccount-import-private-key")
(.multiAccountImportPrivateKey ^js (account-manager)
(types/clj->json {:privateKey private-key})
callback))
(defn verify
"NOTE: beware, the password has to be sha3 hashed"
[address hashed-password callback]
(log/debug "[native-module] verify")
(.verify ^js (account-manager) address hashed-password callback))
(defn verify-database-password
"NOTE: beware, the password has to be sha3 hashed"
[key-uid hashed-password callback]
(log/debug "[native-module] verify-database-password")
(.verifyDatabasePassword ^js (account-manager) key-uid hashed-password callback))
(defn login-with-keycard
[{:keys [key-uid multiaccount-data password chat-key node-config]}]
(log/debug "[native-module] login-with-keycard")
(clear-web-data)
(init-keystore
key-uid
#(.loginWithKeycard ^js (account-manager)
multiaccount-data
password
chat-key
(types/clj->json node-config))))
(defn set-soft-input-mode
[mode]
(log/debug "[native-module] set-soft-input-mode")
@@ -238,11 +331,6 @@
:key input-key})
(.deserializeAndCompressKey ^js (encryption) input-key callback))
(defn serialize-legacy-key
"Compresses an old format public key (0x04...) to the new one zQ..."
[public-key]
(.serializeLegacyKey ^js (encryption) public-key))
(defn compressed-key->public-key
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization"
[public-key deserialization-key callback]
@@ -425,14 +513,6 @@
(let [result (.checkAddressChecksum ^js (utils) address)]
(types/json->clj result)))
(defn toggle-centralized-metrics
[enabled callback]
(.toggleCentralizedMetrics ^js (status) (types/clj->json {:enabled enabled}) callback))
(defn add-centralized-metric
[metric]
(.addCentralizedMetric ^js (status) (types/clj->json metric) #(log/debug "pushed metric" % metric)))
(defn address?
[address]
(log/debug "[native-module] address?")
@@ -453,13 +533,6 @@
(log/debug "[native-module] validate-mnemonic")
(.validateMnemonic ^js (utils) mnemonic callback)))
(defn validate-connection-string
[connection-string]
(log/debug "[native-module] validate-connection-string")
(->> connection-string
(.validateConnectionString ^js (utils))
types/json->clj))
(defn delete-multiaccount
"Delete multiaccount from database, deletes multiaccount's database and
key files."
@@ -570,6 +643,7 @@
(native-utils/promisify-native-module-call create-account-from-private-key private-key))
([private-key callback]
(log/debug "[native-module] create-account-from-private-key")
(.createAccountFromPrivateKey ^js (account-manager)
(types/clj->json {:privateKey private-key})
callback)))
@@ -5,7 +5,6 @@
(defn- get-dimensions
[size]
(case size
:size-32 32
:size-24 24
:size-20 20
nil))
@@ -1,6 +1,5 @@
(ns quo.components.avatars.token-avatar.view
(:require [quo.components.avatars.token-avatar.style :as style]
[quo.components.utilities.token.view :as token]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
@@ -13,14 +12,13 @@
[:map {:closed true}
[:type {:optional true} [:enum :asset :collectible]]
[:context? {:optional true} [:maybe :boolean]]
[:image {:optional true} [:maybe :schema.common/image-source]]
[:token {:optional true} [:maybe [:or :keyword :string]]]
[:image :schema.common/image-source]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [type context? image token network-image container-style]}]
[{:keys [type context? image network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :token-avatar}
@@ -34,11 +32,9 @@
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[token/view
{:size :size-32
:token token
:style (style/image type)
:image-source image}]]
[rn/image
{:source image
:style (style/image type)}]]
(when context?
[rn/image
{:source network-image
@@ -2,7 +2,7 @@
(:require
[quo.components.buttons.button.view :as button]
[quo.components.buttons.predictive-keyboard.style :as style]
[quo.components.info.info-message.view :as info-message]
[quo.components.info.info-message :as info-message]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
@@ -57,17 +57,17 @@
:key-fn str}]
:error
[info-message/view
{:icon :i/info
:size :default
:status :error}
[info-message/info-message
{:icon :i/info
:size :default
:type :error}
text]
:info
[info-message/view
(merge {:icon :i/info
:size :default
:status (if (= type :error) :error :default)}
[info-message/info-message
(merge {:icon :i/info
:size :default
:type (if (= type :error) :error :default)}
(when blur?
{:text-color colors/white-opa-70
:icon-color colors/white-opa-40}))
@@ -14,7 +14,9 @@
[react-native.reanimated :as reanimated]))
(defn drag-gesture
[x-pos disabled? track-width sliding-complete? set-sliding-complete on-complete reset-fn]
[x-pos disabled? track-width sliding-complete?
set-sliding-complete
on-complete reset-fn]
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled (not disabled?))
@@ -26,8 +28,7 @@
(reanimated/set-shared-value x-pos clamped-x)
(when (and reached-end? (not sliding-complete?))
(set-sliding-complete true)
(when on-complete
(on-complete reset-fn))))))
(when on-complete (on-complete reset-fn))))))
(gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)]
@@ -55,10 +56,9 @@
on-track-layout (rn/use-callback
#(set-track-width (oops/oget % "nativeEvent.layout.width")))
reset-fn (rn/use-callback
(fn [keep-at-end-after-slide?]
(fn []
(set-sliding-complete false)
(when-not keep-at-end-after-slide?
(animations/reset-track-position x-pos))))
(animations/reset-track-position x-pos)))
dimensions (rn/use-callback
(partial utils/get-dimensions
(or track-width constants/default-width)
@@ -71,16 +71,14 @@
(dimensions :thumb))
[dimensions])
custom-color (if (= type :danger) :danger customization-color)
gesture (rn/use-memo
(fn []
(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn))
[sliding-complete? disabled? on-complete])]
gesture (rn/use-memo #(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn)
[sliding-complete? disabled?])]
[gesture/gesture-detector
{:gesture gesture}
[reanimated/view
@@ -8,11 +8,10 @@
[react-native.core :as rn]))
(defn- get-icon-color
[blur? danger? theme]
(cond
danger? (colors/theme-colors colors/danger-50 colors/danger-60 theme)
blur? colors/white-opa-70
:else (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
[danger? theme]
(if danger?
(colors/theme-colors colors/danger-50 colors/danger-60 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn- divider
[theme blur?]
@@ -52,7 +51,7 @@
:accessible true
:style (style/left-icon sub-label)}
[icon/icon icon
{:color (or icon-color (get-icon-color blur? danger? theme))
{:color (or icon-color (get-icon-color danger? theme))
:no-color no-icon-color?
:size 20}]])
[rn/view
@@ -85,7 +84,7 @@
:accessible true
:accessibility-label :right-icon-for-action}
[icon/icon right-icon
{:color (get-icon-color blur? danger? theme)
{:color (get-icon-color danger? theme)
:size 20}]])
(when (= state :selected)
[rn/view {:style style/right-icon}
@@ -21,17 +21,15 @@
(colors/theme-colors colors/white colors/neutral-95 theme))})
(defn buttons-container
[actions container-style]
(merge
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20}
container-style))
[actions]
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20})
(def button-container
{:flex-grow 1})
{:flex 1})
(def description-top
{:flex-direction :row
@@ -30,8 +30,7 @@
[:button-two-props {:optional true} [:maybe :map]]
[:scroll? {:optional true} [:maybe :boolean]]
[:blur? {:optional true} [:maybe :boolean]]
[:container-style {:optional true} [:maybe :map]]
[:buttons-container-style {:optional true} [:maybe :map]]]]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(def ^:private role-icon
@@ -43,7 +42,7 @@
(defn- view-internal
[{:keys [actions description description-text description-top-text error-message role button-one-label
button-two-label blur? button-one-props button-two-props scroll? container-style
buttons-container-style context-tag-props]}]
context-tag-props]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:style (merge (style/container scroll? blur? theme) container-style)}
@@ -73,14 +72,14 @@
:context (i18n/label (keyword "t" role))}
context-tag-props)]])
[rn/view {:style (style/buttons-container actions buttons-container-style)}
[rn/view {:style (style/buttons-container actions)}
(when (or (= actions :two-actions)
(= actions :two-vertical-actions))
[button/button
(merge
{:size 40
:container-style style/button-container
:background (when (or blur? scroll?) :blur)
:container-style style/button-container
:theme theme
:accessibility-label :button-two}
button-two-props)
@@ -18,7 +18,7 @@
(defn- left-image
[{:keys [type customization-color account-avatar-emoji account-avatar-type icon-avatar
profile-picture blur?]}]
profile-picture]}]
(case type
:account [account-avatar/view
{:customization-color customization-color
@@ -28,7 +28,6 @@
:keypair [icon-avatar/icon-avatar
{:icon icon-avatar
:border? true
:blur? blur?
:color :neutral}]
:default-keypair [user-avatar/user-avatar
@@ -214,7 +213,6 @@
[rn/view {:style style/left-container}
[left-image
{:type type
:blur? blur?
:customization-color customization-color
:account-avatar-emoji account-avatar-emoji
:account-avatar-type account-avatar-type
+48
View File
@@ -0,0 +1,48 @@
(ns quo.components.info.info-message
(:require
[quo.components.icon :as quo.icons]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn get-color
[k theme]
(case k
:success (colors/resolve-color :success theme)
:error (colors/resolve-color :danger theme)
:warning (colors/resolve-color :warning theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn info-message
"[info-message opts \"message\"]
opts
{:type :default/:success/:error
:size :default/:tiny
:icon :i/info ;; info message icon
:text-color colors/white ;; text color override
:icon-color colors/white ;; icon color override
:no-icon-color? false ;; disable tint color for icon"
[{:keys [type size icon text-color icon-color no-icon-color? style accessibility-label
container-style]} message]
(let [theme (quo.theme/use-theme)
weight (if (= size :default) :regular :medium)
icon-size (if (= size :default) 16 12)
size (if (= size :default) :paragraph-2 :label)
text-color (or text-color (get-color type theme))
icon-color (or icon-color text-color)]
[rn/view
{:style (merge {:flex-direction :row
:align-items :center}
style
container-style)}
[quo.icons/icon icon
{:color icon-color
:no-color no-icon-color?
:size icon-size}]
[text/text
{:accessibility-label accessibility-label
:size size
:weight weight
:style {:color text-color
:margin-horizontal 4}} message]]))
@@ -1,32 +0,0 @@
(ns quo.components.info.info-message.component-spec
(:require
[quo.components.info.info-message.view :as info-message]
[test-helpers.component :as h]))
(h/describe "Info: Info Message"
(h/test "basic render"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-label-text :info-message)))
(h/test "render with correct message"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-text "Message")))
(h/test "render icon"
(h/render-with-theme-provider
[info-message/view
{:status :default
:size :default
:accessibility-label :info-message
:icon :i/placeholder} "Message"])
(h/is-truthy (h/get-by-label-text :icon))))
@@ -1,6 +0,0 @@
(ns quo.components.info.info-message.style)
(def container
{:flex-direction :row
:gap 4
:align-items :center})
@@ -1,53 +0,0 @@
(ns quo.components.info.info-message.view
(:require [quo.components.icon :as icons]
[quo.components.info.info-message.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:status {:optional true} [:maybe [:enum :default :success :error :warning]]]
[:size {:optional true} [:maybe [:enum :default :tiny]]]
[:blur? {:optional true} [:maybe :boolean]]
[:icon :keyword]
[:color {:optional true} [:maybe :string]]
[:text-color {:optional true} [:maybe :string]]
[:icon-color {:optional true} [:maybe :string]]
[:no-icon-color? {:optional true} [:maybe :boolean]]
[:accessibility-label {:optional true} [:maybe :keyword]]
[:container-style {:optional true} [:maybe :map]]]]
[:message :string]]
:any])
(defn- get-color
[status theme blur?]
(case status
:success (if blur? colors/success-60 (colors/resolve-color :success theme))
:error (if blur? colors/danger-60 (colors/resolve-color :danger theme))
:warning (if blur? colors/warning-60 (colors/resolve-color :warning theme))
(if blur? colors/white-opa-40 (colors/theme-colors colors/neutral-50 colors/neutral-40 theme))))
(defn view-internal
[{:keys [status size blur? icon color icon-color text-color no-icon-color? container-style
accessibility-label]} message]
(let [theme (quo.theme/use-theme)
default-color (get-color status theme blur?)
text-color (or text-color color default-color)
icon-color (or icon-color color default-color)]
[rn/view {:style (merge style/container container-style)}
[icons/icon icon
{:size (if (= size :tiny) 12 16)
:color icon-color
:no-color? no-icon-color?}]
[text/text
{:size (if (= size :tiny) :label :paragraph-2)
:accessibility-label accessibility-label
:style {:color text-color}} message]]))
(def view (schema/instrument #'view-internal ?schema))
@@ -31,8 +31,7 @@
:size :paragraph-2}
(:name account-props)]
[address-text/view
{:blur? blur?
:networks networks
{:networks networks
:address (:address account-props)
:format :short}]]]
(when (= action :icon)
@@ -1,58 +0,0 @@
(ns quo.components.list-items.approval-info.component-spec
(:require [quo.components.list-items.approval-info.view :as approval-info]
[test-helpers.component :as h]))
(h/describe "List Items: Approval Info"
(h/test "should render correctly with basic props"
(h/render-with-theme-provider
[approval-info/view
{:type :spending-cap
:label "Spending Cap"
:avatar-props {:image "image"}}])
(h/is-truthy (h/get-by-label-text :approval-info)))
(h/test "should render correctly with label & description"
(h/render-with-theme-provider
[approval-info/view
{:type :spending-cap
:label "Spending Cap"
:description "Description"
:avatar-props {:image "image"}}])
(h/is-truthy (h/get-by-text "Spending Cap"))
(h/is-truthy (h/get-by-text "Description")))
(h/test "on-button-press event is called when button is pressed"
(let [on-button-press (h/mock-fn)]
(h/render-with-theme-provider
[approval-info/view
{:type :spending-cap
:label "Spending Cap"
:button-label "Edit"
:button-icon :i/options
:on-button-press on-button-press
:avatar-props {:image "image"}}])
(h/fire-event :press (h/get-by-text "Edit"))
(h/was-called on-button-press)))
(h/test "on-option-press event is called when option icon is pressed"
(let [on-option-press (h/mock-fn)]
(h/render-with-theme-provider
[approval-info/view
{:type :spending-cap
:label "Spending Cap"
:option-icon :i/options
:on-option-press on-option-press
:avatar-props {:image "image"}}])
(h/fire-event :press (h/get-by-label-text :icon))
(h/was-called on-option-press)))
(h/test "on-avatar-press event is called when avatar is pressed"
(let [on-avatar-press (h/mock-fn)]
(h/render-with-theme-provider
[approval-info/view
{:type :spending-cap
:label "Spending Cap"
:on-avatar-press on-avatar-press
:avatar-props {:image "image"}}])
(h/fire-event :press (h/get-by-label-text :token-avatar))
(h/was-called on-avatar-press))))
@@ -1,36 +0,0 @@
(ns quo.components.list-items.approval-info.style
(:require [quo.foundations.colors :as colors]))
(defn icon-description-color
[blur? theme]
(if blur?
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn container
[description? blur? theme]
{:flex-direction :row
:padding-horizontal 12
:padding-vertical (if description? 8 12)
:border-radius 16
:gap 8
:align-items :center
:border-width 1
:border-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(def labels
{:flex 1
:justify-content :center
:padding-right 4})
(defn label
[blur? theme]
{:color (if blur?
colors/white
(colors/theme-colors colors/neutral-100 colors/white theme))})
(defn description
[blur? theme]
{:color (icon-description-color blur? theme)})
@@ -1,124 +0,0 @@
(ns quo.components.list-items.approval-info.view
(:require [clojure.string :as string]
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.avatars.collection-avatar.view :as collection-avatar]
[quo.components.avatars.community-avatar.view :as community-avatar]
[quo.components.avatars.dapp-avatar.view :as dapp-avatar]
[quo.components.avatars.icon-avatar :as icon-avatar]
[quo.components.avatars.token-avatar.view :as token-avatar]
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
[quo.components.buttons.button.view :as button]
[quo.components.icon :as icon]
[quo.components.list-items.approval-info.style :as style]
[quo.components.markdown.text :as text]
[quo.components.tags.tiny-tag.view :as tiny-tag]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type
[:enum :spending-cap :token-contract :account :spending-contract :network :date-signed
:collectible :address :community :collectible-contract]]
[:avatar-props :map]
[:label :string]
[:description {:optional true} [:maybe :string]]
[:button-label {:optional true} [:maybe :string]]
[:button-icon {:optional true} [:maybe :keyword]]
[:blur? {:optional true} [:maybe :boolean]]
[:unlimited-icon? {:optional true} [:maybe :boolean]]
[:option-icon {:optional true} [:maybe :keyword]]
[:tag-label {:optional true} [:maybe :string]]
[:on-button-press {:optional true} [:maybe fn?]]
[:on-avatar-press {:optional true} [:maybe fn?]]
[:on-option-press {:optional true} [:maybe fn?]]
[:container-style {:optional true} [:maybe :any]]]]]
:any])
(defn- avatar
[{:keys [type avatar-props blur? theme on-press]}]
[rn/pressable {:on-press on-press}
(case type
:account [account-avatar/view (assoc avatar-props :size 32)]
:collectible-contract [collection-avatar/view (assoc avatar-props :size :size-32)]
:spending-contract [dapp-avatar/view avatar-props]
:date-signed [icon-avatar/icon-avatar
(assoc avatar-props
:size :size-32
:opacity 10
:color (if blur?
colors/white
(colors/theme-colors colors/neutral-50
colors/neutral-40
theme)))]
:address [wallet-user-avatar/wallet-user-avatar
(assoc avatar-props
:size :size-32
:monospace? true
:lowercase? true
:neutral? true)]
:community [community-avatar/view avatar-props]
[token-avatar/view
(assoc avatar-props
:type
(if (= type :collectible) :collectible :asset))])])
(defn- view-internal
[{:keys [type avatar-props label description blur? unlimited-icon? container-style
on-option-press on-avatar-press on-button-press button-label button-icon tag-label
option-icon]}]
(let [theme (quo.theme/use-theme)
description? (not (string/blank? description))]
[rn/view
{:style (merge (style/container description? blur? theme) container-style)
:accessibility-label :approval-info}
[avatar
{:type type
:blur? blur?
:theme theme
:on-press on-avatar-press
:avatar-props avatar-props}]
[rn/view
{:style style/labels}
[rn/view
{:style {:flex-direction :row :align-items :center}}
[text/text
{:size :paragraph-1
:weight (if (= type :address) :monospace :semi-bold)
:style (style/label blur? theme)}
label]
(when unlimited-icon?
[icon/icon :i/alert
{:container-style {:margin-left 4}
:size 16
:color (style/icon-description-color blur? theme)}])]
(when description?
[text/text
{:size :paragraph-2
:weight (if (contains? #{:collectible-contract :spending-contract :account :token-contract}
type)
:monospace
:regular)
:style (style/description blur? theme)}
description])]
(when (= type :account) [tiny-tag/view {:label tag-label}])
(when (and (= type :spending-cap) button-icon)
[button/button
{:type :outline
:size 24
:blur? blur?
:icon-left button-icon
:on-press on-button-press}
button-label])
(when option-icon
[rn/pressable {:on-press on-option-press}
[icon/icon option-icon
{:color (style/icon-description-color blur? theme)
:size 20}]])]))
(def view (schema/instrument #'view-internal ?schema))
@@ -34,8 +34,7 @@
(def container-info
{:flex-direction :row
:align-items :center
:flex 1})
:align-items :center})
(def user-info
{:margin-left 8})
+6 -8
View File
@@ -25,16 +25,14 @@
:style {:width 32 :height 32}}]
[rn/view {:style style/user-info}
[text/text
{:weight :semi-bold
:size :paragraph-1
:number-of-lines 1
:style (style/style-text-name theme)}
{:weight :semi-bold
:size :paragraph-1
:style (style/style-text-name theme)}
(:name dapp)]
[text/text
{:weight :regular
:size :paragraph-2
:number-of-lines 1
:style (style/style-text-value theme)}
{:weight :regular
:size :paragraph-2
:style (style/style-text-value theme)}
(:value dapp)]]]
(when right-component
[right-component dapp])]))
@@ -44,14 +44,13 @@
[:label :string]
[:fiat-value :string]
[:token-value :string]
[:container-style {:optional true} [:maybe :map]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:state {:optional true} [:enum :pressed :active :disabled :default]]
[:on-press {:optional true} [:maybe fn?]]]]]
:any])
(defn- view-internal
[{:keys [on-press container-style state customization-color]
[{:keys [on-press state customization-color]
:as props
:or {customization-color :blue}}]
(let [theme (quo.theme/use-theme)
@@ -60,8 +59,7 @@
on-press-out (rn/use-callback #(set-pressed false))
internal-state (if pressed? :pressed state)]
[rn/pressable
{:style (merge (style/container internal-state customization-color theme)
container-style)
{:style (style/container internal-state customization-color theme)
:on-press-in (when-not (= state :disabled) on-press-in)
:on-press-out (when-not (= state :disabled) on-press-out)
:on-press (when-not (= state :disabled) on-press)
+3 -3
View File
@@ -8,7 +8,7 @@
[quo.foundations.colors :as colors]
[react-native.core :as rn]))
(def container
(def container-style
{:margin-horizontal 8
:padding-vertical 8
:padding-horizontal 12
@@ -43,9 +43,9 @@
(defn user
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
untrustworthy? on-press on-long-press accessory customization-color theme
allow-multiple-presses? disabled? container-style]}]
allow-multiple-presses? disabled?]}]
[rn/touchable-highlight
{:style (merge container container-style)
{:style container-style
:underlay-color (colors/resolve-color customization-color theme 5)
:allow-multiple-presses? allow-multiple-presses?
:accessibility-label :user-list
@@ -1,43 +0,0 @@
(ns quo.components.pin-input.pin.view
(:require [quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]))
(defn view
[{:keys [theme state blur?]}]
(let [app-theme (quo.theme/use-theme)
theme (or theme app-theme)]
[rn/view {:style {:width 36 :height 36 :align-items :center :justify-content :center}}
(case state
:active
[rn/view
{:style {:width 16
:height 16
:border-radius 8
:background-color (if blur?
colors/white-opa-20
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme))}}]
:filled
[rn/view
{:style {:width 16
:height 16
:border-radius 8
:background-color (if blur?
colors/white
(colors/theme-colors colors/neutral-100 colors/white theme))}}]
:error
[rn/view
{:style {:width 16
:height 16
:border-radius 8
:background-color (if blur?
colors/danger-60
(colors/theme-colors colors/danger-50 colors/danger-60 theme))}}]
[rn/view
{:style
{:width 12
:height 12
:border-radius 6
:background-color (if blur?
colors/white-opa-20
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme))}}])]))
-27
View File
@@ -1,27 +0,0 @@
(ns quo.components.pin-input.view
(:require [quo.components.markdown.text :as text]
[quo.components.pin-input.pin.view :as pin]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]))
(defn view
[{:keys [number-of-pins number-of-filled-pins error? info]
:or {number-of-pins 6 number-of-filled-pins 0}}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style {:align-items :center}}
[rn/view {:style {:flex-direction :row}}
(for [i (range 1 (inc number-of-pins))]
^{:key i}
[pin/view
{:state (cond
error? :error
(<= i number-of-filled-pins) :filled
(= i (inc number-of-filled-pins)) :active)}])]
(when info
[text/text
{:style {:color (if error?
(colors/theme-colors colors/danger-50 colors/danger-60 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}
:size :paragraph-2}
info])]))
@@ -11,7 +11,7 @@
(defn fallback
[{:keys [theme opacity]}]
[{:opacity opacity}
{:opacity 1
{:opacity default-opacity-for-image
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
:border-style :dashed
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
@@ -60,13 +60,8 @@
:padding-right 0
:padding-top 4})
(defn card-detail-text
[empty-name? theme]
{:flex 1
:margin-right 8
:color (if empty-name?
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
(colors/theme-colors colors/neutral-100 colors/white theme))})
(def card-detail-text
{:flex 1})
(defn card-loader
[opacity]
@@ -120,7 +115,6 @@
[{:opacity opacity}
{:flex 1
:flex-direction :row
:column-gap 8
:opacity default-opacity-for-image}])
(defn supported-file
@@ -1,6 +1,5 @@
(ns quo.components.profile.collectible-list-item.view
(:require
[clojure.string :as string]
[quo.components.avatars.collection-avatar.view :as collection-avatar]
[quo.components.counter.collectible-counter.view :as collectible-counter]
[quo.components.icon :as icon]
@@ -22,7 +21,7 @@
(def cached-load-time 200)
(def error-wait-time 800)
(defn animate-loading-image
(defn on-load-end
[{:keys [load-time set-state loader-opacity image-opacity]}]
(reanimated/animate loader-opacity 0 timing-options-out)
(reanimated/animate image-opacity 1 timing-options-in)
@@ -35,12 +34,6 @@
(set-state (fn [prev-state]
(assoc prev-state :image-loaded? true)))))
(defn on-load
[evt set-state]
(let [source (.. evt -nativeEvent -source)
aspect-ratio (/ (.-width source) (.-height source))]
(set-state (fn [prev-state] (assoc prev-state :image-aspect-ratio aspect-ratio)))))
(defn on-load-error
[set-state]
(js/setTimeout (fn []
@@ -61,12 +54,12 @@
(assoc prev-state :avatar-loaded? true)))))
(defn- fallback-view
[{:keys [label theme image-opacity on-load-end]}]
(rn/use-mount on-load-end)
[reanimated/view {:style (style/fallback {:opacity image-opacity :theme theme})}
[{:keys [label theme image-opacity]}]
[reanimated/view
{:style (style/fallback {:opacity image-opacity
:theme theme})}
[rn/view
[icon/icon :i/sad
{:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
[rn/view {:style {:height 4}}]
[text/text
{:size :paragraph-2
@@ -94,43 +87,31 @@
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
(let [loader-opacity (reanimated/use-shared-value 1)
avatar-opacity (reanimated/use-shared-value 0)
[load-time set-load-time] (rn/use-state (datetime/now))
set-avatar-loaded (fn []
(on-load-avatar {:set-state set-state
:load-time load-time
:loader-opacity loader-opacity
:avatar-opacity avatar-opacity}))
empty-name? (string/blank? collectible-name)]
(rn/use-mount (fn []
(when (string/blank? avatar-image-src)
(set-avatar-loaded))))
[load-time set-load-time] (rn/use-state (datetime/now))]
[rn/view {:style style/card-details-container}
[reanimated/view {:style (style/avatar-container avatar-opacity)}
(cond
(string/blank? avatar-image-src)
[loading-square theme]
community?
[preview-list/view {:type :communities :size :size-20}
(if community?
[preview-list/view
{:type :communities
:size :size-20}
[avatar-image-src]]
:else
[collection-avatar/view
{:size :size-20
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end set-avatar-loaded
:on-load-end #(on-load-avatar {:set-state set-state
:load-time load-time
:loader-opacity loader-opacity
:avatar-opacity avatar-opacity})
:image avatar-image-src}])
[rn/view {:style {:width 8}}]
[text/text
{:size :paragraph-1
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:style (style/card-detail-text empty-name? theme)}
(if empty-name?
(i18n/label :t/unknown)
collectible-name)]]
(when-not (:avatar-loaded? state)
:style style/card-detail-text}
collectible-name]]
(when (not (:avatar-loaded? state))
[reanimated/view {:style (style/card-loader loader-opacity)}
[loading-square theme]
[loading-message theme]])]))
@@ -141,44 +122,39 @@
(let [theme (quo.theme/use-theme)
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
[load-time set-load-time] (rn/use-state (datetime/now))
set-image-loaded (fn []
(animate-loading-image {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity}))]
[load-time set-load-time] (rn/use-state (datetime/now))]
[rn/view {:style (style/card-view-container theme)}
[rn/view {:style {:aspect-ratio 1}}
(cond
(:image-error? state) [fallback-view
{:image-opacity image-opacity
:on-load-end set-image-loaded
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(not supported-file?) [fallback-view
{:image-opacity image-opacity
:on-load-end set-image-loaded
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state)) [loading-image
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(:image-error? state)
[fallback-view
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/cant-fetch-info)}]
(not supported-file?)
[fallback-view
{:image-opacity image-opacity
:theme theme
:label (i18n/label :t/unsupported-file)}]
(not (:image-loaded? state))
[loading-image
{:loader-opacity loader-opacity
:theme theme
:gradient-color-index gradient-color-index}])
(when supported-file?
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load #(on-load % set-state)
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end set-image-loaded
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-error #(on-load-error set-state)
:source image-src}]])]
(when (and (or (:image-loaded? state)
(not supported-file?))
(not (:image-error? state))
counter)
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
[collectible-counter/view
{:container-style style/collectible-counter
:size :size-24
@@ -221,12 +197,11 @@
[reanimated/view {:style (style/supported-file image-opacity)}
[rn/image
{:style style/image
:on-load #(on-load % set-state)
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
:on-load-end #(animate-loading-image {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-load-end #(on-load-end {:load-time load-time
:set-state set-state
:loader-opacity loader-opacity
:image-opacity image-opacity})
:on-error #(on-load-error set-state)
:source image-src}]])
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
@@ -244,13 +219,12 @@
(defn- view-internal
[{:keys [container-style type on-press on-long-press supported-file?]
:as props}]
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-aspect-ratio nil
:image-error? false
:avatar-loaded? false})
(let [[state set-state] (rn/use-state {:image-loaded? false
:image-error? false
:avatar-loaded? false})
collectible-ready? (or (:image-loaded? state) (not supported-file?))]
[rn/pressable
{:on-press (when collectible-ready? #(on-press (:image-aspect-ratio state)))
{:on-press (when collectible-ready? on-press)
:on-long-press (when collectible-ready? on-long-press)
:accessibility-label :collectible-list-item
:style container-style}

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