Compare commits

..
Author SHA1 Message Date
Yevheniia Berdnyk 063d9fd29a e2e: fix for driver creation error 2023-12-22 17:46:38 +02:00
519 changed files with 5491 additions and 6474 deletions
+1 -7
View File
@@ -1,8 +1,2 @@
{:hooks
{:analyze-call
{utils.i18n/label utils.i18n/label
test-helpers.component/get-all-by-translation-text utils.i18n/label
test-helpers.component/get-by-translation-text utils.i18n/label
test-helpers.component/query-all-by-translation-text utils.i18n/label
test-helpers.component/query-by-translation-text utils.i18n/label}}
{:hooks {:analyze-call {utils.i18n/label utils.i18n/label}}
:linters {:status-im.linter/invalid-translation-keyword {:level :error}}}
+5
View File
@@ -194,3 +194,8 @@ test/appium/tests/users.py
## git hooks
lefthook.yml
## clj-kondo
/.clj-kondo/taoensso/*
/.clj-kondo/babashka/*
/.clj-kondo/rewrite-clj/rewrite-clj/config.edn
+1 -5
View File
@@ -18,17 +18,13 @@
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; hang multiline left-hand-thing
;; hang multiline left-hand-thing
;; https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
:fn-map
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
"h/describe-skip" :arg1-body
"h/describe-only" :arg1-body
"h/test" :arg1-body
"h/test-skip" :arg1-body
"h/test-only" :arg1-body
"global.describe" :arg1-body
"global.test" :arg1-body
"list-comp" :binding
+17 -37
View File
@@ -305,7 +305,7 @@ endif
# Get all clojure files, including untracked, excluding removed
define find_all_clojure_files
$$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep -E '((\.clj-kondo\/status-im)|(src).*\.clj[sc]?$$)|((\.clj-kondo\/(status-im|config))|(src).*\.edn$$)|shadow-cljs\.edn')
$$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn)
endef
lint: export TARGET := clojure
@@ -327,7 +327,7 @@ lint-fix: ##@test Run code style checks and fix issues
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
clojure-lsp --ns-exclude-regex ".*/src/status_im/core\.cljs|.*/src/test_helpers/component_tests_preload\.cljs$$" clean-ns && \
clojure-lsp --ns-exclude-regex ".*/src/status_im/core\.cljs$$" clean-ns && \
sh scripts/lint/trailing-newline.sh --fix && \
node_modules/.bin/prettier --write .
@@ -335,44 +335,26 @@ shadow-server: export TARGET := clojure
shadow-server:##@ Start shadow-cljs in server mode for watching
yarn shadow-cljs server
_test-clojure: export TARGET := clojure
_test-clojure: export WATCH ?= false
_test-clojure:
ifeq ($(WATCH), true)
yarn install && \
yarn shadow-cljs compile mocks && \
nodemon --exec "yarn shadow-cljs compile test && node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO" -e cljs
else
yarn install && \
yarn shadow-cljs compile mocks && \
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js "$$SHADOW_OUTPUT_TO"
endif
test-watch: export TARGET := clojure
test-watch: ##@ Watch tests and re-run no changes to cljs files
yarn install
nodemon --exec 'yarn shadow-cljs compile mocks && yarn shadow-cljs compile test && node --require ./test-resources/override.js target/test/test.js' -e cljs
test: export SHADOW_OUTPUT_TO := target/test/test.js
test: export SHADOW_NS_REGEXP := .*-test$$
test: ##@test Run all Clojure tests
test: _test-clojure
test-watch-for-repl: export SHADOW_OUTPUT_TO := target/test/test.js
test-watch-for-repl: export SHADOW_NS_REGEXP := .*-test$$
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
test-watch-for-repl: export TARGET := clojure
test-watch-for-repl: ##@ Watch tests and support REPL connections
yarn install
rm -f target/test/test.js
yarn shadow-cljs compile mocks && \
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
'yarn shadow-cljs watch test --verbose' \
"until [ -f $$SHADOW_OUTPUT_TO ] ; do sleep 1 ; done ; node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO --repl"
'yarn shadow-cljs compile mocks && yarn shadow-cljs watch test --verbose' \
'until [ -f ./target/test/test.js ] ; do sleep 1 ; done ; node --require ./test-resources/override.js ./target/test/test.js --repl'
test-unit: export SHADOW_OUTPUT_TO := target/unit_test/test.js
test-unit: export SHADOW_NS_REGEXP := ^(?!status-im\.integration-test).*-test$$
test-unit: ##@test Run unit tests
test-unit: _test-clojure
test-integration: export SHADOW_OUTPUT_TO := target/integration_test/test.js
test-integration: export SHADOW_NS_REGEXP := ^status-im\.integration-test.*$$
test-integration: ##@test Run integration tests
test-integration: _test-clojure
test: export TARGET := clojure
test: ##@test Run tests once in NodeJS
# Here we create the gyp bindings for nodejs
yarn install
yarn shadow-cljs compile mocks && \
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js target/test/test.js
android-test: jsbundle
android-test: export TARGET := android
@@ -382,7 +364,6 @@ android-test:
component-test-watch: export TARGET := clojure
component-test-watch: export COMPONENT_TEST := true
component-test-watch: export BABEL_ENV := test
component-test-watch: export JEST_USE_SILENT_REPORTER := false
component-test-watch: ##@ Watch tests and re-run no changes to cljs files
@@scripts/check-metro-shadow-process.sh
rm -rf ./component-spec
@@ -392,7 +373,6 @@ component-test-watch: ##@ Watch tests and re-run no changes to cljs files
component-test: export TARGET := clojure
component-test: export COMPONENT_TEST := true
component-test: export BABEL_ENV := test
component-test: export JEST_USE_SILENT_REPORTER := false
component-test: ##@test Run component tests once in NodeJS
@scripts/check-metro-shadow-process.sh
rm -rf ./component-spec
-1
View File
@@ -1,5 +1,4 @@
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
@@ -0,0 +1,268 @@
package im.status.ethereum;
import android.content.Context;
import android.annotation.TargetApi;
import androidx.annotation.Nullable;
import android.app.AlertDialog;
import android.app.ActivityManager;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
import android.preference.PreferenceManager;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.WindowManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.provider.Settings;
import android.os.Bundle;
import android.os.Handler;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
import com.reactnativenavigation.NavigationActivity;
import com.facebook.react.modules.core.PermissionListener;
import androidx.core.splashscreen.SplashScreen;
import java.util.Properties;
import im.status.ethereum.module.StatusThreadPoolExecutor;
import im.status.ethereum.MainApplication;
public class MainActivity extends NavigationActivity
implements ActivityCompat.OnRequestPermissionsResultCallback{
@Nullable private PermissionListener mPermissionListener;
private boolean keepSplash = true;
private final int SPLASH_DELAY = 3200;
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
protected String getMainComponentName() {
return "StatusIm";
}
private static void registerUncaughtExceptionHandler(final Context context) {
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, final Throwable t) {
// High priority, so don't use StatusThreadPoolExecutor
new Thread() {
@Override
public void run() {
Looper.prepare();
new AlertDialog.Builder(context)
.setTitle("Error")
.setMessage(t.toString())
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
defaultUncaughtExceptionHandler.uncaughtException(thread, t);
}
}).show();
Looper.loop();
}
}.start();
}
});
}
private ActivityManager getActivityManager() {
return (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
}
private ActivityManager.MemoryInfo getAvailableMemory(final ActivityManager activityManager) {
final ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
protected void configureStatus() {
// Required because of crazy APN settings redirecting localhost (found in GB)
Properties properties = System.getProperties();
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1");
}
private Intent createNotificationSettingsIntent() {
final Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
} else {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
}
return intent;
}
private void tryToEmit(String eventName, WritableMap event) {
try {
((MainApplication) getApplication()).getReactNativeHost()
.getReactInstanceManager()
.getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("url", event);
} catch(Exception e) {/* we expect NPE on first start, which is OK because we have a fallback */}
}
@Override
public void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
if (intent.getDataString() != null && intent.getData().getScheme().startsWith("app-settings")) {
startActivity(createNotificationSettingsIntent());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
setTheme(R.style.DarkTheme);
// Make sure we get an Alert for every uncaught exceptions
registerUncaughtExceptionHandler(MainActivity.this);
// Report memory details for this application
final ActivityManager activityManager = getActivityManager();
Log.v("RNBootstrap", "Available system memory "+getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.getLargeMemoryClass()+"M");
setSecureFlag();
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
super.onCreate(null);
if (!shouldShowRootedNotification()) {
configureStatus();
} else {
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
.setMessage(getResources().getString(R.string.root_warning))
.setPositiveButton(getResources().getString(R.string.root_okay), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
rejectRootedNotification();
dialog.dismiss();
configureStatus();
}
})
.setNegativeButton(getResources().getString(R.string.root_cancel), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.create();
dialog.show();
}
Runnable r = new Runnable() {
@Override
public void run() {
System.loadLibrary("status-logs");
// when app is started but the Activity has been destroyed, the deep linking url event is
// not emitted when coming back to foreground. This is a workaround. If the problem is
// resolved in react-native this code should be removed
if (getIntent().getData() != null) {
WritableMap event = Arguments.createMap();
event.putString("url", getIntent().getDataString());
// on first start emit will (silently) fail, but the regular deep linking handler will work
tryToEmit("url", event);
}
}
};
splashScreen.setKeepOnScreenCondition(() -> keepSplash);
Handler handler = new Handler();
handler.postDelayed(() -> keepSplash = false, SPLASH_DELAY);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
this.sendBroadcast(intent);
}
private static final String REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification";
private static final Integer FREQUENCY_OF_REMINDER_IN_PERCENT = 5;
private boolean shouldShowRootedNotification() {
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
if (userRejectedRootedNotification()) {
return ((Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT);
} else return true;
} else {
return false;
}
}
private boolean userRejectedRootedNotification() {
SharedPreferences preferences = getPreferences(0);
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false);
}
private void rejectRootedNotification() {
SharedPreferences preferences = getPreferences(0);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true);
editor.commit();
}
private void setSecureFlag() {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
@TargetApi(Build.VERSION_CODES.M)
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
}
@@ -1,236 +0,0 @@
package im.status.ethereum
import android.annotation.TargetApi
import android.app.ActivityManager
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.preference.PreferenceManager
import android.provider.Settings
import android.util.Log
import android.view.WindowManager
import androidx.annotation.Nullable
import androidx.core.app.ActivityCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.facebook.react.modules.core.PermissionListener
import com.reactnativenavigation.NavigationActivity
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView
import im.status.ethereum.MainApplication
import im.status.ethereum.module.StatusThreadPoolExecutor
import java.util.Properties
class MainActivity : NavigationActivity(), ActivityCompat.OnRequestPermissionsResultCallback {
@Nullable
private var mPermissionListener: PermissionListener? = null
private var keepSplash = true
private val SPLASH_DELAY = 3200
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
protected fun getMainComponentName(): String {
return "StatusIm"
}
private fun registerUncaughtExceptionHandler(context: Context) {
val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
// High priority, so don't use StatusThreadPoolExecutor
Thread.setDefaultUncaughtExceptionHandler { thread, t ->
Thread {
Looper.prepare()
AlertDialog.Builder(context)
.setTitle("Error")
.setMessage(t.toString())
.setNegativeButton("Exit") { dialog, id ->
dialog.dismiss()
defaultUncaughtExceptionHandler.uncaughtException(thread, t)
}.show()
Looper.loop()
}.start()
}
}
private fun getActivityManager(): ActivityManager {
return getSystemService(ACTIVITY_SERVICE) as ActivityManager
}
private fun getAvailableMemory(activityManager: ActivityManager): ActivityManager.MemoryInfo {
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo
}
protected fun configureStatus() {
// Required because of crazy APN settings redirecting localhost (found in GB)
val properties = System.getProperties()
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1")
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1")
}
private fun createNotificationSettingsIntent(): Intent {
val intent = Intent()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
} else {
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.data = Uri.parse("package:$packageName")
}
return intent
}
private fun tryToEmit(eventName: String, event: WritableMap) {
try {
(getApplication() as MainApplication).getReactNativeHost()
.getReactInstanceManager()
.getCurrentReactContext()
?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
?.emit("url", event)
} catch (e: Exception) { // we expect NPE on first start, which is OK because we have a fallback
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
if (intent.dataString != null && intent.data!!.scheme!!.startsWith("app-settings")) {
startActivity(createNotificationSettingsIntent())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen();
setTheme(R.style.DarkTheme)
// Make sure we get an Alert for every uncaught exceptions
registerUncaughtExceptionHandler(this)
// Report memory details for this application
val activityManager = getActivityManager()
Log.v("RNBootstrap", "Available system memory " + getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.largeMemoryClass + "M")
setSecureFlag()
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
super.onCreate(null)
if (!shouldShowRootedNotification()) {
configureStatus()
} else {
val dialog = AlertDialog.Builder(this)
.setMessage(resources.getString(R.string.root_warning))
.setPositiveButton(resources.getString(R.string.root_okay)) { dialog, which ->
rejectRootedNotification()
dialog.dismiss()
configureStatus()
}
.setNegativeButton(resources.getString(R.string.root_cancel)) { dialog, which ->
dialog.dismiss()
finishAffinity()
}
.setOnCancelListener {
it.dismiss()
finishAffinity()
}
.create()
dialog.show()
}
val r = Runnable {
System.loadLibrary("status-logs")
// when app is started but the Activity has been destroyed, the deep linking url event is
// not emitted when coming back to foreground. This is a workaround. If the problem is
// resolved in react-native this code should be removed
if (intent.data != null) {
val event = Arguments.createMap()
event.putString("url", intent.dataString)
// on first start emit will (silently) fail, but the regular deep linking handler will work
tryToEmit("url", event)
}
}
splashScreen.setKeepOnScreenCondition { keepSplash }
val handler = Handler()
handler.postDelayed({ keepSplash = false }, SPLASH_DELAY.toLong())
StatusThreadPoolExecutor.getInstance().execute(r)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val intent = Intent("onConfigurationChanged")
intent.putExtra("newConfig", newConfig)
sendBroadcast(intent)
}
private val REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification"
private val FREQUENCY_OF_REMINDER_IN_PERCENT = 5
private fun shouldShowRootedNotification(): Boolean {
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
return if (userRejectedRootedNotification()) {
(Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT
} else true
} else {
return false
}
}
private fun userRejectedRootedNotification(): Boolean {
val preferences = getPreferences(0)
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false)
}
private fun rejectRootedNotification() {
val preferences = getPreferences(0)
val editor = preferences.edit()
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true)
editor.commit()
}
private fun setSecureFlag() {
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
val setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
}
@TargetApi(Build.VERSION_CODES.M)
override fun requestPermissions(permissions: Array<String>, requestCode: Int, listener: PermissionListener) {
mPermissionListener = listener
super.requestPermissions(permissions, requestCode)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (mPermissionListener != null && mPermissionListener!!.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null
}
}
}
@@ -0,0 +1,87 @@
package im.status.ethereum;
import androidx.multidex.MultiDexApplication;
import android.webkit.WebView;
import java.lang.reflect.InvocationTargetException;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import cl.json.RNSharePackage;
import com.facebook.react.ReactNativeHost;
import com.reactnativenavigation.NavigationApplication;
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.reactnativecommunity.blurview.BlurViewPackage;
import java.util.List;
import im.status.ethereum.keycard.RNStatusKeycardPackage;
import im.status.ethereum.module.StatusPackage;
import im.status.ethereum.pushnotifications.PushNotificationPackage;
import im.status.ethereum.StatusOkHttpClientFactory;
import com.facebook.react.bridge.JSIModulePackage;
public class MainApplication extends NavigationApplication {
private final ReactNativeHost mReactNativeHost = new NavigationReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
StatusPackage statusPackage = new StatusPackage(RootUtil.isDeviceRooted());
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(statusPackage);
packages.add(new RNStatusKeycardPackage());
packages.add(new PushNotificationPackage());
packages.add(new BlurViewPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected boolean isNewArchEnabled() {
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}
@Override
protected Boolean isHermesEnabled() {
return BuildConfig.IS_HERMES_ENABLED;
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
OkHttpClientProvider.setOkHttpClientFactory(new StatusOkHttpClientFactory());
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1");
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load();
}
}
}
@@ -1,61 +0,0 @@
package im.status.ethereum
import android.webkit.WebView
import androidx.multidex.MultiDexApplication
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.JSIModulePackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
import com.facebook.react.modules.network.OkHttpClientProvider
import com.reactnativenavigation.NavigationApplication
import com.reactnativenavigation.react.NavigationReactNativeHost
import cl.json.RNSharePackage
import com.reactnativecommunity.blurview.BlurViewPackage
import im.status.ethereum.keycard.RNStatusKeycardPackage
import im.status.ethereum.module.StatusPackage
import im.status.ethereum.pushnotifications.PushNotificationPackage
import im.status.ethereum.StatusOkHttpClientFactory
class MainApplication : NavigationApplication() {
private val mReactNativeHost = object : NavigationReactNativeHost(this) {
override fun getUseDeveloperSupport(): Boolean {
return BuildConfig.DEBUG
}
override fun getPackages(): List<ReactPackage> {
val statusPackage = StatusPackage(RootUtil.isDeviceRooted())
val packages = PackageList(this).getPackages()
packages.add(statusPackage)
packages.add(RNStatusKeycardPackage())
packages.add(PushNotificationPackage())
packages.add(BlurViewPackage())
return packages
}
override fun getJSMainModuleName(): String = "index"
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override fun getReactNativeHost(): ReactNativeHost {
return mReactNativeHost
}
override fun onCreate() {
super.onCreate()
OkHttpClientProvider.setOkHttpClientFactory(StatusOkHttpClientFactory())
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1")
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load()
}
}
}
@@ -1,88 +0,0 @@
package im.status.ethereum
import android.util.Log
import com.facebook.react.modules.network.OkHttpClientFactory
import com.facebook.react.modules.network.OkHttpClientProvider
import okhttp3.OkHttpClient
import okhttp3.tls.HandshakeCertificates
import java.io.ByteArrayInputStream
import java.lang.RuntimeException
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import im.status.ethereum.module.StatusPackage
class StatusOkHttpClientFactory : OkHttpClientFactory {
companion object {
private const val TAG = "StatusOkHttpClientFactory"
private const val SLEEP_DURATION = 500L // milliseconds
}
override fun createNewNetworkModuleClient(): OkHttpClient? {
val certPem = getCertificatePem().takeIf { it.isNotEmpty() }
?: return logAndReturnNull("Certificate is empty, cannot create OkHttpClient without a valid certificate")
val cert = try {
induceSleep()
// Convert PEM certificate string to X509Certificate object
CertificateFactory.getInstance("X.509")
.generateCertificate(ByteArrayInputStream(certPem.toByteArray())) as? X509Certificate
?: return logAndReturnNull("Certificate could not be parsed as non-null")
} catch (e: Exception) {
return logAndReturnNull("Could not parse certificate", e)
}
val clientCertificates = try {
induceSleep()
// Create HandshakeCertificates object with our certificate
HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addTrustedCertificate(cert)
.build()
} catch (e: Exception) {
return logAndReturnNull("Could not build HandshakeCertificates", e)
}
return try {
OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
.build()
} catch (e: Exception) {
logAndReturnNull("Could not create OkHttpClient", e)
}
}
private fun getCertificatePem(): String {
return try {
// Create OkHttpClient with custom SSL socket factory and trust manager
StatusPackage.getImageTLSCert().takeIf { !it.isNullOrBlank() }
?: logAndReturnEmpty("Certificate PEM string is null or empty")
} catch (e: Exception) {
logAndReturnEmpty("Could not getImageTLSCert", e)
}
}
private fun induceSleep() {
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices with
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(SLEEP_DURATION)
} catch (e: InterruptedException) {
Log.e(TAG, "Sleep interrupted", e)
}
}
private fun logAndReturnNull(message: String, e: Exception? = null): Nothing? {
Log.e(TAG, message, e)
return null
}
private fun logAndReturnEmpty(message: String, e: Exception? = null): String {
Log.e(TAG, message, e)
return ""
}
}
@@ -0,0 +1,95 @@
package im.status.ethereum;
import android.util.Log;
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientProvider;
import okhttp3.OkHttpClient;
import okhttp3.Interceptor;
import okhttp3.tls.HandshakeCertificates;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.RuntimeException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import im.status.ethereum.module.StatusPackage;
class StatusOkHttpClientFactory implements OkHttpClientFactory {
private static final String TAG = "StatusOkHttpClientFactory";
public OkHttpClient createNewNetworkModuleClient() {
X509Certificate cert = null;
HandshakeCertificates clientCertificates;
String certPem = "";
// Get TLS PEM certificate from status-go
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices with
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
certPem = getCertificatePem();
} catch(Exception e) {
Log.e(TAG, "Could not getImageTLSCert",e);
}
if (certPem.isEmpty()) {
Log.e(TAG, "Certificate is empty, cannot create OkHttpClient without a valid certificate");
return null;
}
// Convert PEM certificate string to X509Certificate object
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certPem.getBytes()));
} catch(Exception e) {
Log.e(TAG, "Could not parse certificate",e);
}
// Create HandshakeCertificates object with our certificate
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
clientCertificates = new HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addTrustedCertificate(cert)
.build();
} catch(Exception e) {
Log.e(TAG, "Could not build HandshakeCertificates", e);
return null;
}
// Create OkHttpClient with custom SSL socket factory and trust manager
try {
return OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager())
.build();
} catch(Exception e) {
Log.e(TAG, "Could not create OkHttpClient", e);
return null;
}
}
private String getCertificatePem() {
try {
String certPem = StatusPackage.getImageTLSCert();
if (certPem == null || certPem.trim().isEmpty()) {
Log.e(TAG, "Certificate PEM string is null or empty");
return "";
}
return certPem;
} catch (Exception e) {
Log.e(TAG, "Could not getImageTLSCert", e);
return "";
}
}
}
+3 -2
View File
@@ -5,7 +5,7 @@
*/
ext {
// kotlin_version is needed for react-native-camera-kit library
kotlin_version = project.kotlinPluginVersion
kotlin_version = project.kotlinVersion
RNNKotlinVersion = project.kotlinPluginVersion
RNGH_kotlinVersion = project.kotlinPluginVersion
buildToolsVersion = project.buildToolsVersion
@@ -14,7 +14,8 @@ ext {
targetSdkVersion = Integer.valueOf(project.targetSdkVersion)
supportLibVersion = project.supportLibVersion
gradlePluginVersion = project.gradlePluginVersion
kotlinVersion = project.kotlinPluginVersion
kotlinPluginVersion = project.kotlinPluginVersion
ndkVersion = "25.2.9519653"
}
+1
View File
@@ -21,6 +21,7 @@
# $keytool -genkey -v -keystore ./status-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias status
# Version requirements used throughout the Gradle scripts
kotlinVersion=1.7.22
minSdkVersion=24
compileSdkVersion=33
targetSdkVersion=33
+1 -1
View File
@@ -5,7 +5,7 @@ library 'status-jenkins-lib@v1.8.4'
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'macos && arm64 && nix-2.14 && xcode-15.1' }
agent { label 'macos && arm64 && nix-2.14 && xcode-14.3' }
parameters {
string(
+2 -10
View File
@@ -52,24 +52,16 @@ pipeline {
"""
}
}
stage('Unit Tests') {
stage('Tests') {
steps {
sh """#!/bin/bash
set -eo pipefail
make test-unit 2>&1 | tee -a ${LOG_FILE}
make test 2>&1 | tee -a ${LOG_FILE}
"""
}
}
}
}
stage('Integration Tests') {
steps {
sh """#!/bin/bash
set -eo pipefail
make test-integration 2>&1 | tee -a ${LOG_FILE}
"""
}
}
stage('Component Tests') {
steps {
sh """#!/bin/bash
+3 -3
View File
@@ -5,7 +5,7 @@
To run tests:
```
make test
make test
```
@@ -13,10 +13,10 @@ make test
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make test WATCH=true
make test-watch
```
Developers can also manually change the shadow-cljs option `:ns-regex` to control which namespaces the test runner should pick.
Developers can also manually change the shadow-cljs option `:ns-regex` to control which namespaces the test runner should pick.
## Testing with REPL
+3 -3
View File
@@ -340,7 +340,7 @@ PODS:
- React
- react-native-transparent-video (0.1.0):
- React-Core
- react-native-webview (13.6.3):
- react-native-webview (13.3.1):
- React-Core
- React-NativeModulesApple (0.72.5):
- React-callinvoker
@@ -793,7 +793,7 @@ CHECKOUT OPTIONS:
:submodules: true
SPEC CHECKSUMS:
boost: 64032b9e9b938fda23325e68a3771f0fabf414dc
boost: 57d2868c099736d80fcd648bf211b4431e51a558
BVLinearGradient: 612a04ff38e8480291f3379ee5b5a2c571f03fe0
CryptoSwift: c4f2debceb38bf44c80659afe009f71e23e4a082
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
@@ -838,7 +838,7 @@ SPEC CHECKSUMS:
react-native-status: 21f75d492fd311dc111303da38a7a2b23a8a8466
react-native-status-keycard: f1c1227b2d5984c10fb44db68e4bfd2937f31e98
react-native-transparent-video: e484ad11ace8e5f62516e2c5e15efd3cb4df24b0
react-native-webview: 88293a0f23eca8465c0433c023ec632930e644d0
react-native-webview: c2b70afb1d910cdd8810375aecc6c2894e2ba061
React-NativeModulesApple: c6529c637f2e886aab44c48d66cabef2d4fd1138
React-perflogger: cd8886513f68e1c135a1e79d20575c6489641597
React-RCTActionSheet: 726d2615ca62a77ce3e2c13d87f65379cdc73498
@@ -1,5 +1,4 @@
apply plugin: 'com.android.library'
apply plugin: "org.jetbrains.kotlin.android"
def getStatusGoSHA1 = { ->
def statusgoOverridePath = System.getenv("STATUS_GO_SRC_OVERRIDE")
@@ -0,0 +1,78 @@
package im.status.ethereum.module;
import android.view.ActionMode;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.UIBlock;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.views.textinput.ReactEditText;
import javax.annotation.Nonnull;
class RNSelectableTextInputModule extends ReactContextBaseJavaModule {
private ActionMode lastActionMode;
public RNSelectableTextInputModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Nonnull
@Override
public String getName() {
return "RNSelectableTextInputManager";
}
@ReactMethod
public void setupMenuItems(final Integer selectableTextViewReactTag, final Integer textInputReactTag) {
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
RNSelectableTextInputViewManager rnSelectableTextManager = (RNSelectableTextInputViewManager) nvhm.resolveViewManager(selectableTextViewReactTag);
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
rnSelectableTextManager.registerSelectionListener(reactTextView);
}
});
}
@ReactMethod
public void startActionMode(final Integer textInputReactTag) {
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
lastActionMode = reactTextView.startActionMode(reactTextView.getCustomSelectionActionModeCallback(), ActionMode.TYPE_FLOATING);
}
});
}
@ReactMethod
public void hideLastActionMode(){
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
if(lastActionMode!=null){
lastActionMode.finish();
lastActionMode = null;
}
}
});
}
@ReactMethod
public void setSelection(final Integer textInputReactTag, final Integer start, final Integer end){
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
reactTextView.setSelection(start, end);
}
});
}
}
@@ -1,72 +0,0 @@
package im.status.ethereum.module
import android.view.ActionMode
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.uimanager.NativeViewHierarchyManager
import com.facebook.react.uimanager.UIBlock
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.views.textinput.ReactEditText
class RNSelectableTextInputModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private var lastActionMode: ActionMode? = null
override fun getName(): String {
return "RNSelectableTextInputManager"
}
@ReactMethod
fun setupMenuItems(selectableTextViewReactTag: Int?, textInputReactTag: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
selectableTextViewReactTag?.let { selectableTag ->
textInputReactTag?.let { inputTag ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val rnSelectableTextManager = nvhm.resolveViewManager(selectableTag) as RNSelectableTextInputViewManager
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
rnSelectableTextManager.registerSelectionListener(reactTextView)
})
}
}
}
@ReactMethod
fun startActionMode(textInputReactTag: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
textInputReactTag?.let { inputTag ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
lastActionMode = reactTextView.startActionMode(reactTextView.customSelectionActionModeCallback, ActionMode.TYPE_FLOATING)
})
}
}
@ReactMethod
fun hideLastActionMode() {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
uiManager?.addUIBlock(UIBlock { _ ->
lastActionMode?.finish()
lastActionMode = null
})
}
@ReactMethod
fun setSelection(textInputReactTag: Int?, start: Int?, end: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
textInputReactTag?.let { inputTag ->
start?.let { s ->
end?.let { e ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
reactTextView.setSelection(s, e)
})
}
}
}
}
}
@@ -0,0 +1,102 @@
package im.status.ethereum.module;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Menu;
import android.view.MenuItem;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.views.textinput.ReactEditText;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class RNSelectableTextInputViewManager extends ReactViewManager {
public static final String REACT_CLASS = "RNSelectableTextInput";
private String[] _menuItems = new String[0];
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public ReactViewGroup createViewInstance(ThemedReactContext context) {
return new ReactViewGroup(context);
}
@ReactProp(name = "menuItems")
public void setMenuItems(ReactViewGroup reactViewGroup, ReadableArray items) {
if(items != null) {
List<String> result = new ArrayList<String>(items.size());
for (int i = 0; i < items.size(); i++) {
result.add(items.getString(i));
}
this._menuItems = result.toArray(new String[items.size()]);
}
}
public void registerSelectionListener(final ReactEditText view) {
view.setCustomSelectionActionModeCallback(new Callback() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
menu.clear();
for (int i = 0; i < _menuItems.length; i++) {
menu.add(0, i, 0, _menuItems[i]);
}
return true;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int selectionStart = view.getSelectionStart();
int selectionEnd = view.getSelectionEnd();
String selectedText = view.getText().toString().substring(selectionStart, selectionEnd);
// Dispatch event
onSelectNativeEvent(view, item.getItemId(), selectedText, selectionStart, selectionEnd);
mode.finish();
return true;
}
});
}
public void onSelectNativeEvent(ReactEditText view, int eventType, String content, int selectionStart, int selectionEnd) {
WritableMap event = Arguments.createMap();
event.putInt("eventType", eventType);
event.putString("content", content);
event.putInt("selectionStart", selectionStart);
event.putInt("selectionEnd", selectionEnd);
// Dispatch
ReactContext reactContext = (ReactContext) view.getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(view.getId(), "topSelection", event);
}
@Override
public Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.builder()
.put("topSelection", MapBuilder.of("registrationName","onSelection"))
.build();
}
}
@@ -1,85 +0,0 @@
package im.status.ethereum.module
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.WritableMap
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.events.RCTEventEmitter
import com.facebook.react.views.textinput.ReactEditText
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.view.ReactViewManager
class RNSelectableTextInputViewManager : ReactViewManager() {
companion object {
const val REACT_CLASS = "RNSelectableTextInput"
}
private var _menuItems = arrayOf<String>()
override fun getName(): String {
return REACT_CLASS
}
override fun createViewInstance(context: ThemedReactContext): ReactViewGroup {
return ReactViewGroup(context)
}
@ReactProp(name = "menuItems")
fun setMenuItems(reactViewGroup: ReactViewGroup, items: ReadableArray?) {
_menuItems = items?.let {
Array(items.size()) { i -> items.getString(i) }
} ?: arrayOf()
}
fun registerSelectionListener(view: ReactEditText) {
view.customSelectionActionModeCallback = object : ActionMode.Callback {
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
menu.clear()
_menuItems.forEachIndexed { i, item ->
menu.add(0, i, 0, item)
}
return true
}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
return true
}
override fun onDestroyActionMode(mode: ActionMode) {}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
val selectionStart = view.selectionStart
val selectionEnd = view.selectionEnd
val selectedText = view.text.toString().substring(selectionStart, selectionEnd)
onSelectNativeEvent(view, item.itemId, selectedText, selectionStart, selectionEnd)
mode.finish()
return true
}
}
}
private fun onSelectNativeEvent(view: ReactEditText, eventType: Int, content: String, selectionStart: Int, selectionEnd: Int) {
val event: WritableMap = Arguments.createMap().apply {
putInt("eventType", eventType)
putString("content", content)
putInt("selectionStart", selectionStart)
putInt("selectionEnd", selectionEnd)
}
val reactContext = view.context as ReactContext
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(view.id, "topSelection", event)
}
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
return MapBuilder.builder<String, Any>()
.put("topSelection", MapBuilder.of("registrationName", "onSelection"))
.build()
}
}
@@ -0,0 +1,44 @@
package im.status.ethereum.module;
import java.util.concurrent.*;
/** Uses an unbounded queue, but allows timeout of core threads
* (modified case 2 in
* https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html ) */
public class StatusThreadPoolExecutor {
private static final int NUMBER_OF_CORES =
Runtime.getRuntime().availableProcessors();
private static final int THREADS_TO_CORES_RATIO = 100;
private static final int KEEP_ALIVE_TIME = 1;
private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
private final BlockingQueue<Runnable> mQueue;
private final ThreadPoolExecutor mThreadPool;
private StatusThreadPoolExecutor() {
mQueue = new LinkedBlockingQueue<>();
mThreadPool = new ThreadPoolExecutor(
THREADS_TO_CORES_RATIO * NUMBER_OF_CORES,
THREADS_TO_CORES_RATIO * NUMBER_OF_CORES,
KEEP_ALIVE_TIME,
KEEP_ALIVE_TIME_UNIT,
mQueue);
// Allow pool to drain
mThreadPool.allowCoreThreadTimeOut(true);
}
/** Pugh singleton */
private static class Holder {
private static StatusThreadPoolExecutor instance = new StatusThreadPoolExecutor();
}
public static StatusThreadPoolExecutor getInstance() {
return Holder.instance;
}
public void execute(final Runnable r) {
mThreadPool.execute(r);
}
}
@@ -1,47 +0,0 @@
package im.status.ethereum.module
import java.util.concurrent.*
/**
* Uses an unbounded queue but allows timeout of core threads
* (modified case 2 in
* https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html )
*/
class StatusThreadPoolExecutor private constructor() {
private val NUMBER_OF_CORES: Int = Runtime.getRuntime().availableProcessors()
private val THREADS_TO_CORES_RATIO: Int = 100
private val KEEP_ALIVE_TIME: Int = 1
private val KEEP_ALIVE_TIME_UNIT: TimeUnit = TimeUnit.SECONDS
private val mQueue: BlockingQueue<Runnable> = LinkedBlockingQueue()
private val mThreadPool: ThreadPoolExecutor
init {
mThreadPool = ThreadPoolExecutor(
THREADS_TO_CORES_RATIO * NUMBER_OF_CORES,
THREADS_TO_CORES_RATIO * NUMBER_OF_CORES,
KEEP_ALIVE_TIME.toLong(),
KEEP_ALIVE_TIME_UNIT,
mQueue
)
// Allow pool to drain
mThreadPool.allowCoreThreadTimeOut(true)
}
/** Singleton holder */
private object Holder {
val instance = StatusThreadPoolExecutor()
}
companion object {
@JvmStatic
fun getInstance(): StatusThreadPoolExecutor {
return Holder.instance
}
}
fun execute(r: Runnable) {
mThreadPool.execute(r)
}
}
@@ -0,0 +1,23 @@
package android.util;
public class Log {
public static int d(String tag, String msg) {
System.out.println("DEBUG: " + tag + ": " + msg);
return 0;
}
public static int i(String tag, String msg) {
System.out.println("INFO: " + tag + ": " + msg);
return 0;
}
public static int w(String tag, String msg) {
System.out.println("WARN: " + tag + ": " + msg);
return 0;
}
public static int e(String tag, String msg) {
System.out.println("ERROR: " + tag + ": " + msg);
return 0;
}
}
@@ -1,27 +0,0 @@
package android.util
object Log {
@JvmStatic
fun d(tag: String, msg: String): Int {
println("DEBUG: $tag: $msg")
return 0
}
@JvmStatic
fun i(tag: String, msg: String): Int {
println("INFO: $tag: $msg")
return 0
}
@JvmStatic
fun w(tag: String, msg: String): Int {
println("WARN: $tag: $msg")
return 0
}
@JvmStatic
fun e(tag: String, msg: String): Int {
println("ERROR: $tag: $msg")
return 0
}
}
+244 -447
View File
File diff suppressed because it is too large Load Diff
-15
View File
@@ -1,23 +1,19 @@
androidx.activity:activity:1.0.0
androidx.activity:activity:1.0.0-rc01
androidx.activity:activity:1.2.4
androidx.annotation:annotation-experimental:1.1.0
androidx.annotation:annotation:1.1.0
androidx.annotation:annotation:1.2.0
androidx.annotation:annotation:1.3.0
androidx.appcompat:appcompat-resources:1.1.0-rc01
androidx.appcompat:appcompat-resources:1.2.0
androidx.appcompat:appcompat-resources:1.3.1
androidx.appcompat:appcompat-resources:1.4.1
androidx.appcompat:appcompat-resources:1.4.2
androidx.appcompat:appcompat:1.1.0-rc01
androidx.appcompat:appcompat:1.2.0
androidx.appcompat:appcompat:1.3.1
androidx.appcompat:appcompat:1.4.1
androidx.appcompat:appcompat:1.4.2
androidx.arch.core:core-common:2.0.0
androidx.arch.core:core-common:2.1.0
androidx.arch.core:core-common:2.1.0-rc01
androidx.arch.core:core-runtime:2.0.0
androidx.arch.core:core-runtime:2.1.0
androidx.asynclayoutinflater:asynclayoutinflater:1.0.0
@@ -39,7 +35,6 @@ androidx.coordinatorlayout:coordinatorlayout:1.1.0
androidx.core:core-ktx:1.6.0
androidx.core:core-splashscreen:1.0.0
androidx.core:core:1.1.0
androidx.core:core:1.1.0-rc01
androidx.core:core:1.2.0
androidx.core:core:1.6.0
androidx.core:core:1.7.0
@@ -72,7 +67,6 @@ androidx.exifinterface:exifinterface:1.2.0
androidx.exifinterface:exifinterface:1.3.2
androidx.fragment:fragment:1.0.0
androidx.fragment:fragment:1.1.0
androidx.fragment:fragment:1.1.0-rc01
androidx.fragment:fragment:1.3.6
androidx.interpolator:interpolator:1.0.0
androidx.legacy:legacy-support-core-ui:1.0.0
@@ -80,7 +74,6 @@ androidx.legacy:legacy-support-core-utils:1.0.0
androidx.legacy:legacy-support-v4:1.0.0
androidx.lifecycle:lifecycle-common:2.0.0
androidx.lifecycle:lifecycle-common:2.1.0
androidx.lifecycle:lifecycle-common:2.1.0-rc01
androidx.lifecycle:lifecycle-common:2.3.1
androidx.lifecycle:lifecycle-common:2.4.0
androidx.lifecycle:lifecycle-livedata-core:2.0.0
@@ -91,13 +84,11 @@ androidx.lifecycle:lifecycle-livedata:2.1.0
androidx.lifecycle:lifecycle-process:2.4.0
androidx.lifecycle:lifecycle-runtime:2.0.0
androidx.lifecycle:lifecycle-runtime:2.1.0
androidx.lifecycle:lifecycle-runtime:2.1.0-rc01
androidx.lifecycle:lifecycle-runtime:2.3.1
androidx.lifecycle:lifecycle-runtime:2.4.0
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1
androidx.lifecycle:lifecycle-viewmodel:2.0.0
androidx.lifecycle:lifecycle-viewmodel:2.1.0
androidx.lifecycle:lifecycle-viewmodel:2.1.0-rc01
androidx.lifecycle:lifecycle-viewmodel:2.3.1
androidx.loader:loader:1.0.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
@@ -108,7 +99,6 @@ androidx.recyclerview:recyclerview:1.0.0
androidx.recyclerview:recyclerview:1.1.0
androidx.resourceinspection:resourceinspection-annotation:1.0.0
androidx.savedstate:savedstate:1.0.0
androidx.savedstate:savedstate:1.0.0-rc01
androidx.savedstate:savedstate:1.1.0
androidx.slidingpanelayout:slidingpanelayout:1.0.0
androidx.startup:startup-runtime:1.0.0
@@ -126,11 +116,8 @@ androidx.transition:transition:1.1.0
androidx.transition:transition:1.2.0
androidx.transition:transition:1.2.0-rc01
androidx.vectordrawable:vectordrawable-animated:1.1.0
androidx.vectordrawable:vectordrawable-animated:1.1.0-rc01
androidx.vectordrawable:vectordrawable:1.1.0
androidx.vectordrawable:vectordrawable:1.1.0-rc01
androidx.versionedparcelable:versionedparcelable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.0-rc01
androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager2:viewpager2:1.0.0
androidx.viewpager:viewpager:1.0.0
@@ -618,8 +605,6 @@ com.parse.bolts:bolts-tasks:1.4.0
com.squareup.okhttp3:okhttp-tls:4.9.2
com.squareup.okhttp3:okhttp-urlconnection:4.9.2
com.squareup.okhttp3:okhttp:4.9.2
com.squareup.okio:okio-metadata:2.8.0
com.squareup.okio:okio:2.8.0
com.squareup.okio:okio:2.9.0
com.squareup:javapoet:1.8.0
com.squareup:javapoet:1.10.0
+30 -43
View File
@@ -1,4 +1,3 @@
https://dl.google.com/dl/android/maven2/androidx/activity/activity/1.0.0-rc01/activity-1.0.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/activity/activity/1.0.0/activity-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/activity/activity/1.1.0/activity-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/activity/activity/1.2.4/activity-1.2.4.pom
@@ -11,14 +10,12 @@ https://dl.google.com/dl/android/maven2/androidx/annotation/annotation/1.1.0-rc0
https://dl.google.com/dl/android/maven2/androidx/annotation/annotation/1.1.0/annotation-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/annotation/annotation/1.2.0/annotation-1.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/annotation/annotation/1.3.0/annotation-1.3.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.1.0-rc01/appcompat-resources-1.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.1.0/appcompat-resources-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.2.0/appcompat-resources-1.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.3.1/appcompat-resources-1.3.1.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.4.1/appcompat-resources-1.4.1.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat-resources/1.4.2/appcompat-resources-1.4.2.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.0.0/appcompat-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.1.0-rc01/appcompat-1.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.1.0/appcompat-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.2.0/appcompat-1.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.3.1/appcompat-1.3.1.pom
@@ -26,7 +23,6 @@ https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.4.1/appco
https://dl.google.com/dl/android/maven2/androidx/appcompat/appcompat/1.4.2/appcompat-1.4.2.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-common/2.0.0/core-common-2.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-common/2.0.1/core-common-2.0.1.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-common/2.1.0-rc01/core-common-2.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-common/2.1.0/core-common-2.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-runtime/2.0.0/core-runtime-2.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/arch/core/core-runtime/2.1.0/core-runtime-2.1.0.pom
@@ -87,7 +83,6 @@ https://dl.google.com/dl/android/maven2/androidx/exifinterface/exifinterface/1.1
https://dl.google.com/dl/android/maven2/androidx/exifinterface/exifinterface/1.2.0/exifinterface-1.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/exifinterface/exifinterface/1.3.2/exifinterface-1.3.2.pom
https://dl.google.com/dl/android/maven2/androidx/fragment/fragment/1.0.0/fragment-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/fragment/fragment/1.1.0-rc01/fragment-1.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/fragment/fragment/1.1.0/fragment-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/fragment/fragment/1.2.5/fragment-1.2.5.pom
https://dl.google.com/dl/android/maven2/androidx/fragment/fragment/1.3.6/fragment-1.3.6.pom
@@ -96,7 +91,6 @@ https://dl.google.com/dl/android/maven2/androidx/legacy/legacy-support-core-ui/1
https://dl.google.com/dl/android/maven2/androidx/legacy/legacy-support-core-utils/1.0.0/legacy-support-core-utils-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/legacy/legacy-support-v4/1.0.0/legacy-support-v4-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common/2.0.0/lifecycle-common-2.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common/2.1.0-rc01/lifecycle-common-2.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common/2.1.0/lifecycle-common-2.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common/2.2.0/lifecycle-common-2.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common/2.3.1/lifecycle-common-2.3.1.pom
@@ -109,7 +103,6 @@ https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-livedata/2.
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-livedata/2.1.0/lifecycle-livedata-2.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-process/2.4.0/lifecycle-process-2.4.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-runtime/2.0.0/lifecycle-runtime-2.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-runtime/2.1.0-rc01/lifecycle-runtime-2.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-runtime/2.1.0/lifecycle-runtime-2.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-runtime/2.2.0/lifecycle-runtime-2.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-runtime/2.3.1/lifecycle-runtime-2.3.1.pom
@@ -118,7 +111,6 @@ https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel-s
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel-savedstate/2.2.0/lifecycle-viewmodel-savedstate-2.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel-savedstate/2.3.1/lifecycle-viewmodel-savedstate-2.3.1.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel/2.0.0/lifecycle-viewmodel-2.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel/2.1.0-rc01/lifecycle-viewmodel-2.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel/2.1.0/lifecycle-viewmodel-2.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel/2.2.0/lifecycle-viewmodel-2.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-viewmodel/2.3.1/lifecycle-viewmodel-2.3.1.pom
@@ -130,7 +122,6 @@ https://dl.google.com/dl/android/maven2/androidx/print/print/1.0.0/print-1.0.0.p
https://dl.google.com/dl/android/maven2/androidx/recyclerview/recyclerview/1.0.0/recyclerview-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/recyclerview/recyclerview/1.1.0/recyclerview-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/resourceinspection/resourceinspection-annotation/1.0.0/resourceinspection-annotation-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/savedstate/savedstate/1.0.0-rc01/savedstate-1.0.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/savedstate/savedstate/1.0.0/savedstate-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/savedstate/savedstate/1.1.0/savedstate-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/slidingpanelayout/slidingpanelayout/1.0.0/slidingpanelayout-1.0.0.pom
@@ -152,10 +143,8 @@ https://dl.google.com/dl/android/maven2/androidx/transition/transition/1.1.0/tra
https://dl.google.com/dl/android/maven2/androidx/transition/transition/1.2.0-rc01/transition-1.2.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/transition/transition/1.2.0/transition-1.2.0.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable-animated/1.0.0/vectordrawable-animated-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable-animated/1.1.0-rc01/vectordrawable-animated-1.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable-animated/1.1.0/vectordrawable-animated-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable/1.0.0/vectordrawable-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable/1.1.0-rc01/vectordrawable-1.1.0-rc01.pom
https://dl.google.com/dl/android/maven2/androidx/vectordrawable/vectordrawable/1.1.0/vectordrawable-1.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/versionedparcelable/versionedparcelable/1.0.0/versionedparcelable-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/versionedparcelable/versionedparcelable/1.1.0-rc01/versionedparcelable-1.1.0-rc01.pom
@@ -537,7 +526,6 @@ https://repo.maven.apache.org/maven2/commons-codec/commons-codec/1.16.0/commons-
https://repo.maven.apache.org/maven2/commons-io/commons-io/2.4/commons-io-2.4.pom
https://repo.maven.apache.org/maven2/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.pom
https://repo.maven.apache.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.pom
https://repo.maven.apache.org/maven2/commons-logging/commons-logging/1.3.0/commons-logging-1.3.0.pom
https://repo.maven.apache.org/maven2/com/adobe/xmp/xmpcore/6.1.11/xmpcore-6.1.11.pom
https://repo.maven.apache.org/maven2/com/afollestad/material-dialogs/commons/0.9.6.0/commons-0.9.6.0.pom
https://repo.maven.apache.org/maven2/com/afollestad/material-dialogs/core/0.9.6.0/core-0.9.6.0.pom
@@ -621,25 +609,25 @@ https://repo.maven.apache.org/maven2/com/facebook/soloader/soloader/0.10.1/soloa
https://repo.maven.apache.org/maven2/com/facebook/soloader/soloader/0.10.5/soloader-0.10.5.pom
https://repo.maven.apache.org/maven2/com/facebook/yoga/proguard-annotations/1.19.0/proguard-annotations-1.19.0.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.11.1/jackson-annotations-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.16.1/jackson-annotations-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.16.0-rc1/jackson-annotations-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.11.1/jackson-core-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.16.1/jackson-core-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-core/2.16.0-rc1/jackson-core-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.11.1/jackson-databind-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.16.1/jackson-databind-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.16.0-rc1/jackson-databind-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.11.1/jackson-dataformat-xml-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-base/2.11.1/jackson-base-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-base/2.16.1/jackson-base-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-base/2.16.0-rc1/jackson-base-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-bom/2.11.1/jackson-bom-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-bom/2.16.1/jackson-bom-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-bom/2.16.0-rc1/jackson-bom-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-parent/2.11/jackson-parent-2.11.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-parent/2.16/jackson-parent-2.16.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/jackson-parent/2.16-rc1/jackson-parent-2.16-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-modules-base/2.11.1/jackson-modules-base-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-modules-base/2.16.1/jackson-modules-base-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-modules-base/2.16.0-rc1/jackson-modules-base-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.11.1/jackson-module-jaxb-annotations-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.16.1/jackson-module-jaxb-annotations-2.16.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.16.0-rc1/jackson-module-jaxb-annotations-2.16.0-rc1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/jackson/module/jackson-module-kotlin/2.11.1/jackson-module-kotlin-2.11.1.pom
https://repo.maven.apache.org/maven2/com/fasterxml/oss-parent/38/oss-parent-38.pom
https://repo.maven.apache.org/maven2/com/fasterxml/oss-parent/56/oss-parent-56.pom
https://repo.maven.apache.org/maven2/com/fasterxml/oss-parent/55/oss-parent-55.pom
https://repo.maven.apache.org/maven2/com/fasterxml/woodstox/woodstox-core/6.2.1/woodstox-core-6.2.1.pom
https://repo.maven.apache.org/maven2/com/github/bumptech/glide/annotations/4.12.0/annotations-4.12.0.pom
https://repo.maven.apache.org/maven2/com/github/bumptech/glide/compiler/4.12.0/compiler-4.12.0.pom
@@ -697,7 +685,7 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotatio
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.4.0/error_prone_annotations-2.4.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.7.1/error_prone_annotations-2.7.1.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.9.0/error_prone_annotations-2.9.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.24.0/error_prone_annotations-2.24.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.0.18/error_prone_parent-2.0.18.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.1/error_prone_parent-2.3.1.pom
@@ -706,11 +694,10 @@ https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.4.0/error_prone_parent-2.4.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.7.1/error_prone_parent-2.7.1.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.9.0/error_prone_parent-2.9.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.24.0/error_prone_parent-2.24.0.pom
https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.23.0/error_prone_parent-2.23.0.pom
https://repo.maven.apache.org/maven2/com/google/flatbuffers/flatbuffers-java/1.12.0/flatbuffers-java-1.12.0.pom
https://repo.maven.apache.org/maven2/com/google/google/1/google-1.pom
https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom
https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/22.0/guava-parent-22.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/23.0/guava-parent-23.0.pom
@@ -722,8 +709,8 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/29.0-jre/guav
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-android/guava-parent-30.1-android.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-jre/guava-parent-30.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/31.0.1-jre/guava-parent-31.0.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/33.0.0-jre/guava-parent-33.0.0-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/33.0.0-jre/guava-testlib-33.0.0-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/32.1.3-jre/guava-parent-32.1.3-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/32.1.3-jre/guava-testlib-32.1.3-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/17.0/guava-17.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/22.0/guava-22.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/23.0/guava-23.0.pom
@@ -735,7 +722,7 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-android/guava-30.1-android.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-jre/guava-30.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/32.1.3-jre/guava-32.1.3-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/1.0/listenablefuture-1.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom
https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.pom
@@ -769,8 +756,8 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.10.0/
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.13.0/protobuf-parent-3.13.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.17.2/protobuf-parent-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/4.0.0-rc-2/protobuf-parent-4.0.0-rc-2.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.2.0/truth-parent-1.2.0.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth/1.2.0/truth-1.2.0.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.1.5/truth-parent-1.1.5.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth/1.1.5/truth-1.1.5.pom
https://repo.maven.apache.org/maven2/com/ibm/icu/icu4j/53.1/icu4j-53.1.pom
https://repo.maven.apache.org/maven2/com/intellij/annotations/12.0/annotations-12.0.pom
https://repo.maven.apache.org/maven2/com/parse/bolts/bolts-tasks/1.4.0/bolts-tasks-1.4.0.pom
@@ -785,8 +772,7 @@ https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/3.12.1/okhttp-3
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/4.9.2/okhttp-4.9.2.pom
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.9.1/parent-3.9.1.pom
https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.12.1/parent-3.12.1.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.7.0/okio-jvm-3.7.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-metadata/2.8.0/okio-metadata-2.8.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-jvm/3.6.0/okio-jvm-3.6.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.13.0/okio-parent-1.13.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.15.0/okio-parent-1.15.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.17.4/okio-parent-1.17.4.pom
@@ -795,7 +781,7 @@ https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.15.0/okio-1.15.0.p
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.17.4/okio-1.17.4.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.8.0/okio-2.8.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.9.0/okio-2.9.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.7.0/okio-3.7.0.pom
https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.6.0/okio-3.6.0.pom
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.0/all-1.2.0.pom
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.1/all-1.2.1.pom
https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.2/all-1.2.2.pom
@@ -913,13 +899,13 @@ https://repo.maven.apache.org/maven2/junit/junit/4.13.2/junit-4.13.2.pom
https://repo.maven.apache.org/maven2/me/zhanghai/android/materialprogressbar/library/1.4.2/library-1.4.2.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.11.13/byte-buddy-agent-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.11.19/byte-buddy-agent-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.10/byte-buddy-agent-1.14.10.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.9/byte-buddy-agent-1.14.9.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.11.13/byte-buddy-parent-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.11.19/byte-buddy-parent-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.10/byte-buddy-parent-1.14.10.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.9/byte-buddy-parent-1.14.9.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.11.13/byte-buddy-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.11.19/byte-buddy-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.10/byte-buddy-1.14.10.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.9/byte-buddy-1.14.9.pom
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna-platform/5.6.0/jna-platform-5.6.0.pom
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/1/jvnet-parent-1.pom
@@ -963,7 +949,6 @@ https://repo.maven.apache.org/maven2/org/apache/apache/16/apache-16.pom
https://repo.maven.apache.org/maven2/org/apache/apache/18/apache-18.pom
https://repo.maven.apache.org/maven2/org/apache/apache/21/apache-21.pom
https://repo.maven.apache.org/maven2/org/apache/apache/29/apache-29.pom
https://repo.maven.apache.org/maven2/org/apache/apache/31/apache-31.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-compress/1.12/commons-compress-1.12.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-compress/1.20/commons-compress-1.20.pom
@@ -981,7 +966,6 @@ https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/39/common
https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/42/commons-parent-42.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/48/commons-parent-48.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/58/commons-parent-58.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/65/commons-parent-65.pom
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.pom
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.2.6/httpclient-4.2.6.pom
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.pom
@@ -1034,7 +1018,7 @@ https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.8.1/che
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.pom
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.5.0/checker-qual-3.5.0.pom
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.pom
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.42.0/checker-qual-3.42.0.pom
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.40.0/checker-qual-3.40.0.pom
https://repo.maven.apache.org/maven2/org/codehaus/codehaus-parent/4/codehaus-parent-4.pom
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy-xml/3.0.10/groovy-xml-3.0.10.pom
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy/3.0.10/groovy-3.0.10.pom
@@ -1156,7 +1140,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.5.31/
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.20/kotlin-reflect-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.22/kotlin-reflect-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/2.0.0-Beta2/kotlin-reflect-2.0.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.9.20/kotlin-reflect-1.9.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.20/kotlin-scripting-common-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.22/kotlin-scripting-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.6.20/kotlin-scripting-compiler-embeddable-1.6.20.pom
@@ -1187,6 +1171,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.6.21/kotlin-stdlib-common-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.22/kotlin-stdlib-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.10/kotlin-stdlib-common-1.9.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.2.71/kotlin-stdlib-jdk7-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.20/kotlin-stdlib-jdk7-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.50/kotlin-stdlib-jdk7-1.3.50.pom
@@ -1199,6 +1184,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.5
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.20/kotlin-stdlib-jdk7-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.22/kotlin-stdlib-jdk7-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.10/kotlin-stdlib-jdk7-1.9.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.2.71/kotlin-stdlib-jdk8-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.20/kotlin-stdlib-jdk8-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.50/kotlin-stdlib-jdk8-1.3.50.pom
@@ -1210,6 +1196,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.5
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.5.31/kotlin-stdlib-jdk8-1.5.31.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.22/kotlin-stdlib-jdk8-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.10/kotlin-stdlib-jdk8-1.9.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.1.3-2/kotlin-stdlib-1.1.3-2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.0/kotlin-stdlib-1.2.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.20/kotlin-stdlib-1.2.20.pom
@@ -1233,8 +1220,8 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.20/k
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.6.21/kotlin-stdlib-1.6.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.22/kotlin-stdlib-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.21/kotlin-stdlib-1.9.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/2.0.0-Beta2/kotlin-stdlib-2.0.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.10/kotlin-stdlib-1.9.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.20/kotlin-stdlib-1.9.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.22/kotlin-tooling-core-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.20/kotlin-tooling-metadata-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.6.20/kotlin-util-io-1.6.20.pom
@@ -1249,14 +1236,14 @@ https://repo.maven.apache.org/maven2/org/json/json/20231013/json-20231013.pom
https://repo.maven.apache.org/maven2/org/jsoup/jsoup/1.13.1/jsoup-1.13.1.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.9.2/junit-bom-5.9.2.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.9.3/junit-bom-5.9.3.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.10.1/junit-bom-5.10.1.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.10.0/junit-bom-5.10.0.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.7.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8.1/stax-ex-1.8.1.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8/stax-ex-1.8.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/2.1.0/stax-ex-2.1.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/3.12.4/mockito-core-3.12.4.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/4.0.0/mockito-core-4.0.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.8.0/mockito-core-5.8.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.7.0/mockito-core-5.7.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-inline/4.0.0/mockito-inline-4.0.0.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.2/objenesis-parent-3.2.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.3/objenesis-parent-3.3.pom
+9 -10
View File
@@ -12,8 +12,8 @@ stdenv.mkDerivation {
"patchBuildIdPhase"
"patchKeyChainPhase"
"patchGlogPhase"
"patchBoostPodSpec"
"installPhase"
"patchJestPhase"
"installPhase"
];
# First symlink all modules as is
@@ -56,6 +56,13 @@ stdenv.mkDerivation {
'-Wl,--build-id=none'
'';
# Remove when we upgrade jest to 29
patchJestPhase = ''
substituteInPlace ./node_modules/react-native/jest/setup.js --replace \
'jest.now()' \
'Date.now'
'';
installPhase = ''
mkdir -p $out
cp -R node_modules $out/
@@ -78,14 +85,6 @@ stdenv.mkDerivation {
--replace 'export CXX="' '#export CXX="'
'';
# to fix pod checksum issue : https://github.com/facebook/react-native/issues/42180
# TODO remove this patch after upgrading to react-native 0.73.2
patchBoostPodSpec = ''
substituteInPlace ./node_modules/react-native/third-party-podspecs/boost.podspec \
--replace 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2' \
'https://sourceforge.net/projects/boost/files/boost/1.76.0/boost_1_76_0.tar.bz2' \
'';
# The ELF types are incompatible with the host platform, so let's not even try
# TODO: Use Android NDK to strip binaries manually
dontPatchELF = true;
+1 -1
View File
@@ -69,7 +69,7 @@ in {
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
openjdk = super.openjdk11_headless;
xcodeWrapper = super.xcodeenv.composeXcodeWrapper {
version = "15.0";
version = "14.0";
allowHigher = true;
};
go = super.go_1_19;
+1 -1
View File
@@ -19,7 +19,7 @@
ios = {targets ? [ "ios/arm64" "iossimulator/amd64"]}: callPackage ./build.nix {
platform = "ios";
platformVersion = "11.0";
platformVersion = "8.0";
outputFileName = "Statusgo.xcframework";
inherit meta source goBuildLdFlags targets;
};
+6 -6
View File
@@ -26,7 +26,6 @@
"create-react-class": "^15.6.2",
"emojilib": "^2.4.0",
"eth-phishing-detect": "^1.2.0",
"form-data": "^4.0.0",
"functional-red-black-tree": "^1.0.1",
"i18n-js": "^3.3.0",
"jsc-android": "^250231.0.0",
@@ -67,7 +66,7 @@
"react-native-svg": "13.10.0",
"react-native-touch-id": "^4.4.1",
"react-native-transparent-video": "git+https://github.com/status-im/react-native-transparent-video.git#refs/tags/0.1.1",
"react-native-webview": "13.6.3",
"react-native-webview": "13.3.1",
"react-syntax-highlighter": "^15.5.0",
"rn-emoji-keyboard": "0.7.0",
"tdigest": "^0.1.1"
@@ -82,17 +81,18 @@
"@babel/register": "7.0.0",
"@jest/globals": "^25.1.0",
"@mapbox/node-pre-gyp": "^1.0.9",
"@testing-library/jest-native": "^5.4.3",
"@testing-library/react-native": "^12.4.2",
"@testing-library/jest-native": "^5.0.0",
"@testing-library/react-native": "^11.2.0",
"@tsconfig/react-native": "^3.0.0",
"@types/jest": "^28.1.6",
"@types/react": "^18.0.24",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.7.0",
"concurrently": "^7.6.0",
"jest": "^29.7.0",
"jest": "^26.6.3",
"jest-circus": "^26.0.0",
"jest-environment-node": "^26.6.2",
"jest-image-snapshot": "^5.1.0",
"jest-silent-reporter": "^0.5.0",
"metro-react-native-babel-preset": "0.76.8",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh
if rg --quiet --multiline '^\(ns.*\n^\s*\(:require\n(^\s*(;|#_).*\n)*(^\s*\[status-im\.setup\.i18n-resources\W)' src/status_im/core.cljs src/test_helpers/component_tests_preload.cljs; then
if rg --quiet --multiline '^\(ns.*\n^\s*\(:require\n(^\s*(;|#_).*\n)*(^\s*\[status-im\.setup\.i18n-resources\W)' src/status_im/core.cljs; then
exit 0
elif [ $? -eq 1 ]; then
echo "status-im.setup.i18n-resources must be loaded first (be the first one in ns :require form) in status-im.core"
+5 -7
View File
@@ -108,13 +108,13 @@
;; produced by the target :mocks below and redefines node require
;; function to use the mocks instead of the rn libraries
:test
{:output-to #shadow/env "SHADOW_OUTPUT_TO"
{:output-to "target/test/test.js"
:output-dir "target/test"
:optimizations :simple
:target :node-test
:dev {:devtools {:preloads [status-im.setup.schema-preload]}}
;; Uncomment line below to `make test-watch` a specific file
:ns-regexp #shadow/env "SHADOW_NS_REGEXP"
;; :ns-regexp "status-im.subs.messages-test$"
:main legacy.status-im.test-runner/main
;; set :ui-driven to true to let shadow-cljs inject node-repl
:ui-driven true
@@ -150,10 +150,9 @@
:source-map false}}
:component-test {:target :npm-module
:entries [;; We need to tell shadow-cljs to compile
;; the preloads namespaces because they
;; will be used directly by Jest in the
;; option setupFilesAfterEnv.
test-helpers.component-tests-preload
;; the preloads namespace because it will
;; be used directly by Jest in the option
;; setupFilesAfterEnv.
status-im.setup.schema-preload
quo.core-spec
@@ -162,6 +161,5 @@
:output-dir "component-spec"
:closure-defines {schema.core/throw-on-error? true}
:compiler-options {:warnings-as-errors false
:warnings {:fn-deprecated false}
:static-fns false
:infer-externs true}}}}
+3 -30
View File
@@ -39,16 +39,14 @@ export function interpolateNavigationViewOpacity(props) {
});
}
export function messagesListOnScroll(distanceFromListTop, chatListScrollY, callback) {
export function messagesListOnScroll(distanceFromListTop, callback) {
return function (event) {
'worklet';
const currentY = event.contentOffset.y;
const layoutHeight = event.layoutMeasurement.height;
const contentSizeY = event.contentSize.height - layoutHeight;
const newDistance = contentSizeY - currentY;
distanceFromListTop.value = newDistance;
chatListScrollY.value = currentY;
runOnJS(callback)(layoutHeight, newDistance);
distanceFromListTop.value = contentSizeY - currentY;
runOnJS(callback)(currentY, layoutHeight);
};
}
@@ -65,28 +63,3 @@ export function placeholderZIndex(isCalculationsComplete) {
return isCalculationsComplete.value ? 0 : 2;
});
}
export function scrollDownButtonOpacity(chatListScrollY, isComposerFocused, windowHeight) {
return useDerivedValue(function () {
'worklet';
if (isComposerFocused.value) {
return 0;
} else {
return chatListScrollY.value > windowHeight * 0.75 ? 1 : 0;
}
});
}
export function jumpToButtonOpacity(scrollDownButtonOpacity, isComposerFocused) {
return useDerivedValue(function () {
'worklet';
return withTiming(scrollDownButtonOpacity.value == 1 || isComposerFocused.value ? 0 : 1);
});
}
export function jumpToButtonPosition(scrollDownButtonOpacity, isComposerFocused) {
return useDerivedValue(function () {
'worklet';
return withTiming(scrollDownButtonOpacity.value == 1 || isComposerFocused.value ? 35 : 0);
});
}
@@ -4,7 +4,7 @@
[legacy.status-im.data-store.messages :as data-store.messages]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.list.events :as message-list]
[status-im.contexts.chat.messages.list.events :as message-list]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
@@ -6,9 +6,9 @@
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.contexts.chat.messenger.messages.delete-message.events :as delete-message]
[status-im.contexts.chat.messenger.messages.list.events :as message-list]
[status-im.contexts.chat.messenger.messages.list.state :as view.state]
[status-im.contexts.chat.messages.delete-message.events :as delete-message]
[status-im.contexts.chat.messages.list.events :as message-list]
[status-im.contexts.chat.messages.list.state :as view.state]
[utils.re-frame :as rf]))
(defn- message-loaded?
@@ -3,7 +3,7 @@
[cljs.test :refer-macros [deftest is testing]]
[legacy.status-im.chat.models.loading :as loading]
[legacy.status-im.chat.models.message :as message]
[status-im.contexts.chat.messenger.messages.list.state :as list.state]))
[status-im.contexts.chat.messages.list.state :as list.state]))
(deftest add-received-message-test
(with-redefs [message/add-message #(identity %1)]
+2 -2
View File
@@ -4,8 +4,8 @@
[legacy.status-im.data-store.chats :as chats-store]
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]
[status-im.contexts.chat.contacts.events :as contacts-store]
[status-im.contexts.chat.messenger.messages.list.events :as message-list]
[status-im.contexts.chat.messages.list.events :as message-list]
[status-im.contexts.contacts.events :as contacts-store]
[status-im.contexts.shell.activity-center.events :as activity-center]
[status-im.navigation.events :as navigation]
[utils.re-frame :as rf]))
@@ -6,7 +6,7 @@
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.utils.mobile-sync :as utils]
[legacy.status-im.wallet.core :as wallet]
[status-im.contexts.chat.home.add-new-contact.events :as add-new-contact]
[status-im.contexts.add-new-contact.events :as add-new-contact]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
@@ -9,8 +9,8 @@
[quo.foundations.typography :as typography]
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.delete-message-for-me.events]
[status-im.contexts.chat.messenger.messages.delete-message.events]
[status-im.contexts.chat.messages.delete-message-for-me.events]
[status-im.contexts.chat.messages.delete-message.events]
[utils.i18n :as i18n]
[utils.re-frame :as rf])
(:require-macros [legacy.status-im.utils.views :refer [defview letsubs]]))
@@ -8,7 +8,7 @@
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.link-previews-settings.styles :as styles]
[re-frame.core :as re-frame]
[status-im.contexts.chat.messenger.messages.link-preview.events]
[status-im.contexts.chat.messages.link-preview.events]
[utils.i18n :as i18n]))
(defn prepare-urls-items-data
@@ -63,7 +63,14 @@
:track-icon :face-id})
(h/describe "slide-button"
(h/setup-fake-timers)
(h/before-each
(fn []
(h/use-fake-timers)))
(h/after-each
(fn []
(h/clear-all-timers)
(h/use-real-timers)))
(h/test "render the correct text"
(h/render [slide-button/view default-props])
@@ -17,3 +17,5 @@
(h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0))
(-> (h/expect @selected)
(.toStrictEqual :blue)))))
@@ -27,18 +27,14 @@
(let [selected (reagent/atom default-selected)
{window-width :width} (rn/get-window)
ref (atom nil)]
(rn/use-effect
(fn []
(js/setTimeout
(fn []
(let [index (.indexOf colors/account-colors default-selected)]
(when (and @ref (>= index 0))
(some-> ^js @ref
(.scrollToIndex #js
{:animated true
:index index
:viewPosition 0.5})))))
50)))
(rn/use-effect #(js/setTimeout (fn []
(.scrollToIndex ^js @ref
#js
{:animated true
:index (.indexOf colors/account-colors
default-selected)
:viewPosition 0.5}))
50))
[rn/flat-list
{:ref #(reset! ref %)
;; TODO: using :feng-shui? temporarily while b & w is being developed.
@@ -8,7 +8,7 @@
utils.money))
(defn view-internal
[{:keys [value icon theme style accessibility-label text-size]}]
[{:keys [value icon theme style accessibility-label]}]
[rn/view
{:style (merge style/container style)
:accessibility-label accessibility-label}
@@ -19,7 +19,7 @@
:resize-mode :center
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}]
[quo.text/text
{:size (or text-size :paragraph-1)
{:size :paragraph-1
:weight :regular
:style (style/text theme)} (utils.money/format-amount value)]])
@@ -6,25 +6,34 @@
(h/describe "select-profile component"
(h/test "render component"
(h/render [strength-divider/view {:type :okay}])
(h/is-truthy (h/get-by-label-text :strength-divider)))
(-> (h/expect (h/get-by-label-text :strength-divider))
(.toBeTruthy)))
(h/test "render component with :type :very-weak"
(h/render [strength-divider/view {:type :very-weak}])
(h/is-truthy (h/get-by-translation-text :t/strength-divider-very-weak-label)))
(-> (h/expect (h/get-by-translation-text :strength-divider-very-weak-label))
(.toBeTruthy)))
(h/test "render component with :type :weak"
(h/render [strength-divider/view {:type :weak}])
(h/is-truthy (h/get-by-translation-text :t/strength-divider-weak-label)))
(-> (h/expect (h/get-by-translation-text :strength-divider-weak-label))
(.toBeTruthy)))
(h/test "render component with :type :okay"
(h/render [strength-divider/view {:type :okay}])
(h/is-truthy (h/get-by-translation-text :t/strength-divider-okay-label)))
(-> (h/expect (h/get-by-translation-text :strength-divider-okay-label))
(.toBeTruthy)))
(h/test "render component with :type :strong"
(h/render [strength-divider/view {:type :strong}])
(h/is-truthy (h/get-by-translation-text :t/strength-divider-strong-label)))
(-> (h/expect (h/get-by-translation-text :strength-divider-strong-label))
(.toBeTruthy)))
(h/test "render component with :type :very-strong"
(h/render [strength-divider/view {:type :very-strong}])
(h/is-truthy (h/get-by-translation-text :t/strength-divider-very-strong-label)))
(-> (h/expect (h/get-by-translation-text :strength-divider-very-strong-label))
(.toBeTruthy)))
(h/test "render component with :type :alert"
(h/render [strength-divider/view {:type :alert} "Text message"])
(h/is-truthy (h/get-by-text "Text message")))
(-> (h/expect (h/get-by-text "Text message"))
(.toBeTruthy)))
(h/test "render component with :type :info"
(h/render [strength-divider/view {:type :info} "Text Info"])
(h/is-truthy (h/get-by-text "Text Info"))))
(-> (h/expect (h/get-by-text "Text Info"))
(.toBeTruthy))))
@@ -6,7 +6,14 @@
[test-helpers.component :as h]))
(h/describe "drawer-buttons"
(h/setup-fake-timers)
(h/before-each
(fn []
(h/use-fake-timers)))
(h/after-each
(fn []
(h/clear-all-timers)
(h/use-real-timers)))
(h/test "the top heading and subheading render"
(h/render [drawer-buttons/view
@@ -30,6 +37,7 @@
(-> (js/expect (h/get-by-text "bottom-sub-heading"))
(.toBeTruthy)))
(h/test "it clicks the top card"
(let [event (h/mock-fn)]
(with-redefs [safe-area/get-top (fn [] 10)]
@@ -71,7 +71,7 @@
:icon-avatar :i/placeholder
:type :keypair}])
(h/is-truthy (h/get-by-text "Title"))
(-> (h/expect (h/get-by-translation-text :t/on-device))
(-> (h/expect (h/get-by-translation-text :on-device))
(.toBeTruthy)))
(h/test "component renders in keypair type when keycard? is true"
@@ -81,7 +81,7 @@
:icon-avatar :i/placeholder
:type :keypair}])
(h/is-truthy (h/get-by-text "Title"))
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
(-> (h/expect (h/get-by-translation-text :on-keycard))
(.toBeTruthy)))
(h/test "component renders in default-keypair type"
@@ -13,10 +13,7 @@
{:time-frame :empty}])
(h/is-truthy (h/get-by-label-text :illustration)))
;; NOTE: Throws error:
;; _reactNative.Animated.timing(widthValue2, {
;; Cannot read properties of undefined (reading 'timing')
(h/test-skip "render 1 week wallet graph"
(h/test "render 1 week wallet graph"
(h/render [wallet-graph/view
{:time-frame :1-week
:data (data 7)}])
@@ -18,9 +18,7 @@
(with-redefs [clipboard/get-string #(% "")]
(h/render [address-input/address-input {:ens-regex ens-regex}])
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input)
:placeholder-text-color
colors/neutral-40)))
(h/has-prop (h/get-by-label-text :address-text-input) :placeholder-text-color colors/neutral-40)))
(h/test "on focus with blur? true"
(with-redefs [clipboard/get-string #(% "")]
@@ -40,33 +38,27 @@
{:scanned-value scanned-value
:on-change-text on-change-text
:ens-regex ens-regex}])
(-> (h/wait-for #(h/get-by-label-text :clear-button))
(.then (fn []
(h/was-called-with on-change-text scanned-value)
(h/has-prop (h/get-by-label-text :address-text-input)
:default-value
scanned-value)))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))
(h/was-called-with on-change-text scanned-value)
(h/has-prop (h/get-by-label-text :address-text-input) :default-value scanned-value))))
(h/test "clear icon is shown when input has text"
(with-redefs [clipboard/get-string #(% "")]
(h/render [address-input/address-input
{:scanned-value "scanned value"
:ens-regex ens-regex}])
(-> (h/wait-for #(h/get-by-label-text :clear-button-container))
(.then #(h/is-truthy (h/get-by-label-text :clear-button))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button-container)))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))))
(h/test "on blur with text and blur? false"
(with-redefs [clipboard/get-string #(% "")]
(h/render [address-input/address-input
{:scanned-value "scanned value"
:ens-regex ens-regex}])
(-> (h/wait-for #(h/get-by-label-text :clear-button))
(.then (fn []
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/fire-event :on-blur (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input)
:placeholder-text-color
colors/neutral-30))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/fire-event :on-blur (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input) :placeholder-text-color colors/neutral-30)))
(h/test "on blur with text blur? true"
(with-redefs [clipboard/get-string #(% "")]
@@ -74,22 +66,19 @@
{:scanned-value "scanned value"
:blur? true
:ens-regex ens-regex}])
(-> (h/wait-for #(h/get-by-label-text :clear-button))
(.then (fn []
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/fire-event :on-blur (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input)
:placeholder-text-color
colors/neutral-80-opa-20))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/fire-event :on-blur (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input)
:placeholder-text-color
colors/neutral-80-opa-20)))
(h/test "on blur with no text and blur? false"
(with-redefs [clipboard/get-string #(% "")]
(h/render [address-input/address-input {:ens-regex ens-regex}])
(h/fire-event :on-focus (h/get-by-label-text :address-text-input))
(h/fire-event :on-blur (h/get-by-label-text :address-text-input))
(h/has-prop (h/get-by-label-text :address-text-input)
:placeholder-text-color
colors/neutral-40)))
(h/has-prop (h/get-by-label-text :address-text-input) :placeholder-text-color colors/neutral-40)))
(h/test "on blur with no text blur? true"
(with-redefs [clipboard/get-string #(% "")]
@@ -109,10 +98,9 @@
{:scanned-value "scanned value"
:on-clear on-clear
:ens-regex ens-regex}])
(-> (h/wait-for #(h/get-by-label-text :clear-button))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :clear-button))
(h/was-called on-clear)))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))
(h/fire-event :press (h/get-by-label-text :clear-button))
(h/was-called on-clear))))
(h/test "on-focus is called"
(let [on-focus (h/mock-fn)]
@@ -134,22 +122,18 @@
(let [on-scan (h/mock-fn)]
(with-redefs [clipboard/get-string #(% "")]
(h/render [address-input/address-input {:on-scan on-scan}])
(-> (h/wait-for #(h/get-by-label-text :scan-button))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :scan-button))
(h/was-called on-scan)))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :scan-button)))
(h/fire-event :press (h/get-by-label-text :scan-button))
(h/was-called on-scan))))
(h/test "paste from clipboard"
(let [clipboard "clipboard"]
(with-redefs [clipboard/get-string #(% clipboard)]
(h/render [address-input/address-input {:ens-regex ens-regex}])
(h/is-truthy (h/query-by-label-text :paste-button))
(h/wait-for #(h/is-truthy (h/get-by-label-text :paste-button)))
(h/fire-event :press (h/get-by-label-text :paste-button))
(-> (h/wait-for #(h/get-by-label-text :clear-button))
(.then (fn []
(h/has-prop (h/get-by-label-text :address-text-input)
:default-value
clipboard)))))))
(h/wait-for #(h/is-truthy (h/get-by-label-text :clear-button)))
(h/has-prop (h/get-by-label-text :address-text-input) :default-value clipboard))))
(h/test "ENS loading state and call on-detect-ens"
(let [clipboard "test.eth"
@@ -158,12 +142,11 @@
(h/render [address-input/address-input
{:on-detect-ens on-detect-ens
:ens-regex ens-regex}])
(h/is-truthy (h/query-by-label-text :paste-button))
(h/wait-for #(h/is-truthy (h/get-by-label-text :paste-button)))
(h/fire-event :press (h/get-by-label-text :paste-button))
(-> (h/wait-for #(h/is-falsy (h/query-by-label-text :clear-button)))
(.then (fn []
(h/wait-for #(h/get-by-label-text :loading-button-container))))
(.then #(h/was-called on-detect-ens))))))
(h/wait-for #(h/is-falsy (h/get-by-label-text :clear-button)))
(h/wait-for #(h/is-truthy (h/get-by-label-text :loading-button-container)))
(h/was-called on-detect-ens))))
(h/test "ENS valid state and call on-detect-ens"
(let [clipboard "test.eth"
@@ -173,12 +156,11 @@
{:on-detect-ens on-detect-ens
:valid-ens-or-address? true
:ens-regex ens-regex}])
(h/is-truthy (h/query-by-label-text :paste-button))
(h/wait-for #(h/is-truthy (h/get-by-label-text :paste-button)))
(h/fire-event :press (h/get-by-label-text :paste-button))
(-> (h/wait-for #(h/is-falsy (h/query-by-label-text :clear-button)))
(.then (fn []
(h/wait-for #(h/get-by-label-text :positive-button-container))))
(.then #(h/was-called on-detect-ens))))))
(h/wait-for #(h/is-falsy (h/get-by-label-text :clear-button)))
(h/wait-for #(h/is-truthy (h/get-by-label-text :positive-button-container)))
(h/was-called on-detect-ens))))
(h/test "address loading state and call on-detect-address"
(let [clipboard "0x2f88d65f3cb52605a54a833ae118fb1363acccd2"
@@ -187,24 +169,21 @@
(h/render [address-input/address-input
{:on-detect-address on-detect-address
:address-regex address-regex}])
(h/is-truthy (h/query-by-label-text :paste-button))
(h/wait-for #(h/is-truthy (h/get-by-label-text :paste-button)))
(h/fire-event :press (h/get-by-label-text :paste-button))
(-> (h/wait-for #(h/is-falsy (h/query-by-label-text :clear-button)))
(.then (fn []
(h/wait-for #(h/get-by-label-text :loading-button-container))))
(.then #(h/was-called on-detect-address))))))
(h/wait-for #(h/is-falsy (h/get-by-label-text :clear-button)))
(h/wait-for #(h/is-truthy (h/get-by-label-text :loading-button-container)))
(h/was-called on-detect-address))))
(h/test "address valid state and call on-detect-address"
(let [clipboard "0x2f88d65f3cb52605a54a833ae118fb1363acccd2"
on-detect-address (h/mock-fn)]
(with-redefs [clipboard/get-string #(% clipboard)]
(h/render [address-input/address-input
{:on-detect-address on-detect-address
:address-regex address-regex
:valid-ens-or-address? true}])
(h/is-truthy (h/query-by-label-text :paste-button))
{:on-detect-address on-detect-address
:address-regex address-regex}])
(h/wait-for #(h/is-truthy (h/get-by-label-text :paste-button)))
(h/fire-event :press (h/get-by-label-text :paste-button))
(-> (h/wait-for #(h/is-falsy (h/query-by-label-text :clear-button)))
(.then (fn []
(h/wait-for #(h/get-by-label-text :positive-button-container))))
(.then #(h/was-called on-detect-address)))))))
(h/wait-for #(h/is-falsy (h/get-by-label-text :clear-button)))
(h/wait-for #(h/is-truthy (h/get-by-label-text :positive-button-container)))
(h/was-called on-detect-address)))))
+2 -2
View File
@@ -61,7 +61,7 @@
:container-style])
(defn- base-input
[{:keys [on-change-text on-char-limit-reach weight default-value]}]
[{:keys [on-change-text on-char-limit-reach weight]}]
(let [status (reagent/atom :default)
internal-on-focus #(reset! status :focus)
internal-on-blur #(reset! status :default)
@@ -72,7 +72,7 @@
(if (> height min-height)
(reset! multiple-lines? true)
(reset! multiple-lines? false)))
char-count (reagent/atom (count default-value))
char-count (reagent/atom 0)
update-char-limit! (fn [new-text char-limit]
(when on-change-text (on-change-text new-text))
(let [amount-chars (count new-text)]
@@ -13,17 +13,16 @@
{:value ""
:max-length 24}])
(h/fire-event :on-focus (h/query-by-label-text :profile-title-input))
(-> (h/wait-for #(h/get-by-text "00"))
(.then #(h/is-truthy (h/query-by-text "/24")))))
(h/wait-for #(h/is-truthy (h/query-by-text "00")))
(h/is-truthy (h/query-by-text "/24")))
(h/test "renders with max length digits and character count"
(h/render [title-input/view
{:default-value "abc"
:max-length 24}
"abc"])
:max-length 24} "abc"])
(h/fire-event :on-focus (h/query-by-label-text :profile-title-input))
(-> (h/wait-for #(h/get-by-text "03"))
(.then #(h/is-truthy (h/query-by-text "/24")))))
(h/wait-for #(h/is-truthy (h/query-by-text "03")))
(h/is-truthy (h/query-by-text "/24")))
(h/test "text updates on change"
(let [on-change-text (h/mock-fn)]
@@ -6,9 +6,7 @@
(h/describe "keycard component"
(h/test "Render of keycard component when: holder-name prop is not set"
(h/render [keycard/keycard])
(h/is-truthy (h/get-by-translation-text :t/empty-keycard)))
(h/is-truthy (h/get-by-translation-text :empty-keycard)))
(h/test "Render of keycard component when: holder-name prop is set"
(let [holder-name "Alisha"]
(h/render [keycard/keycard {:holder-name holder-name}])
(h/is-truthy (h/get-by-translation-text :t/user-keycard {:name holder-name})))))
(h/render [keycard/keycard {:holder-name "Alisha"}])
(h/is-truthy (h/get-by-translation-text :user-keycard))))
@@ -1,72 +0,0 @@
(ns quo.components.links.internal-link-card.channel.style
(:require [quo.foundations.colors :as colors]))
(defn loading-circle
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 16
:height 16
:border-radius 16})
(defn loading-first-line-bar
[theme margin-right?]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 72
:margin-right (when margin-right? 4)
:height 16
:border-radius 6})
(defn loading-second-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 112
:height 8
:border-radius 6
:margin-bottom 17})
(defn loading-thumbnail-box
[theme size]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:height (if (= :message size) 139 160)
:border-radius 12})
(defn thumbnail
[size]
{:width "100%"
:height (if (= :message size) 139 160)
:margin-top 8
:border-radius 12})
(defn container
[size theme]
{:border-width 1
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme)
:border-radius 16
:padding-horizontal 12
:padding-top 10
:padding-bottom 12
:height (if (= :message size) 215 236)
:width (if (= :message size) 295 335)})
(def header-container
{:flex-direction :row
:align-items :center})
(def title
{:margin-bottom 2})
(def logo
{:margin-right 6
:width 16
:height 16
:border-radius 8})
(defn channel-chevron-props
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(def row-spacing
{:flex-direction :row
:margin-bottom 13})
@@ -1,92 +0,0 @@
(ns quo.components.links.internal-link-card.channel.view
(:require
[quo.components.icon :as icon]
[quo.components.links.internal-link-card.channel.style :as style]
[quo.components.links.internal-link-card.schema :as component-schema]
[quo.components.markdown.text :as text]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
(defn- description-comp
[description]
[rn/view {:style {:margin-bottom 4}}
[text/text
{:size :paragraph-2
:number-of-lines 3
:accessibility-label :description}
description]])
(defn- title-comp
[title channel-name theme]
[rn/view
{:style {:flex-direction :row
:align-items :center}}
[text/text
{:size :paragraph-1
:number-of-lines 1
:weight :semi-bold
:style style/title
:accessibility-label :title}
title]
[icon/icon :i/chevron-right (style/channel-chevron-props theme)]
[text/text
{:size :paragraph-1
:number-of-lines 1
:weight :semi-bold
:style style/title
:accessibility-label :title}
channel-name]])
(defn- banner-comp
[thumbnail size]
[rn/image
{:style (style/thumbnail size)
:source thumbnail
:accessibility-label :banner}])
(defn- logo-comp
[logo]
[rn/image
{:accessibility-label :logo
:source logo
:style (assoc style/logo :margin-bottom 2)}])
(defn- loading-view
[theme size]
[rn/view
{:accessibility-label :loading-channel-link-view
:style {:height 215}}
[rn/view {:style {:flex-direction :row}}
[rn/view {:style style/row-spacing}
[rn/view {:style (style/loading-circle theme)}]
[rn/view {:style (style/loading-first-line-bar theme true)}]]
[rn/view {:style style/row-spacing}
[rn/view {:style (style/loading-circle theme)}]
[rn/view {:style (style/loading-first-line-bar theme false)}]]]
[rn/view {:style (style/loading-second-line-bar theme)}]
[rn/view {:style (style/loading-thumbnail-box theme size)}]])
(defn view-internal
[{:keys [title description loading? icon banner
theme on-press channel-name size]
:or {channel-name "empty name"}}]
[rn/pressable
{:style (style/container size theme)
:accessibility-label :internal-link-card
:on-press on-press}
(if loading?
[loading-view theme size]
[:<>
[rn/view {:style style/header-container}
(when icon
[logo-comp icon])
[title-comp title channel-name theme]]
(when description
[description-comp description])
(when banner
[banner-comp banner size])])])
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))
@@ -1,87 +0,0 @@
(ns quo.components.links.internal-link-card.community.style
(:require [quo.foundations.colors :as colors]))
(defn loading-circle
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 16
:height 16
:border-radius 16})
(defn loading-stat
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 32
:height 8
:border-radius 16})
(def loading-stat-container
{:flex-direction :row
:align-items :center
:margin-right 12
:margin-bottom -6})
(defn loading-first-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 145
:height 16
:border-radius 6})
(defn loading-second-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 112
:height 8
:border-radius 6
:margin-bottom 17})
(defn loading-thumbnail-box
[theme size]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:height (if (= :message size) 139 160)
:border-radius 12})
(defn thumbnail
[size]
{:width "100%"
:height (if (= :message size) 139 160)
:margin-top 6
:border-radius 12})
(defn container
[size theme]
{:border-width 1
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme)
:border-radius 16
:padding-horizontal 12
:padding-top 10
:padding-bottom 12
:height (if (= :message size) 245 266)
:width (if (= :message size) 295 335)})
(def header-container
{:flex-direction :row
:align-items :center})
(def title
{:margin-bottom 2})
(def logo
{:width 16
:height 16
:border-radius 8
:margin-right 4
:margin-bottom 2})
(def row-spacing
{:flex-direction :row
:margin-bottom 12
:margin-top 4})
(def stat-container
{:flex-direction :row
:margin-top 12})
@@ -1,96 +0,0 @@
(ns quo.components.links.internal-link-card.community.view
(:require
[quo.components.community.community-stat.view :as community-stat]
[quo.components.links.internal-link-card.community.style :as style]
[quo.components.links.internal-link-card.schema :as component-schema]
[quo.components.markdown.text :as text]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[schema.core :as schema]))
(defn- description-comp
[description members-count active-members-count]
[rn/view
[text/text
{:size :paragraph-2
:number-of-lines 3
:accessibility-label :description}
description]
[rn/view {:style style/stat-container}
[community-stat/view
{:value members-count
:icon :i/members
:accessibility-label :members-count
:style {:margin-right 12}
:text-size :paragraph-2}]
(when active-members-count
[community-stat/view
{:value active-members-count
:icon :i/active-members
:accessibility-label :active-members-count
:text-size :paragraph-2}])]])
(defn- title-comp
[title]
[text/text
{:size :paragraph-1
:number-of-lines 1
:weight :semi-bold
:style style/title
:accessibility-label :title}
title])
(defn- thumbnail-comp
[thumbnail size]
[rn/image
{:style (style/thumbnail size)
:source thumbnail
:accessibility-label :thumbnail}])
(defn- logo-comp
[logo]
[rn/image
{:accessibility-label :logo
:source logo
:style style/logo}])
(defn- stat-loading
[theme]
[rn/view {:style style/loading-stat-container}
[rn/view {:style (style/loading-circle theme)}]
[rn/view {:style (style/loading-stat theme)}]])
(defn- loading-view
[theme size]
[rn/view {:accessibility-label :loading-community-link-view}
[rn/view {:style style/row-spacing}
[rn/view {:style (style/loading-circle theme)}]
[rn/view {:style (style/loading-first-line-bar theme)}]]
[rn/view {:style (style/loading-second-line-bar theme)}]
[rn/view {:style style/row-spacing}
[stat-loading theme]
[stat-loading theme]]
[rn/view {:style (style/loading-thumbnail-box theme size)}]])
(defn- view-internal
[{:keys [title description loading? icon banner members-count active-members-count
theme on-press size]}]
[rn/pressable
{:style (style/container size theme)
:accessibility-label :internal-link-card
:on-press on-press}
(if loading?
[loading-view theme size]
[:<>
[rn/view {:style style/header-container}
(when icon
[logo-comp icon])
[title-comp title]]
(when description
[description-comp description members-count active-members-count])
(when banner
[thumbnail-comp banner size])])])
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))
@@ -1,81 +0,0 @@
(ns quo.components.links.internal-link-card.component-spec
(:require
[quo.components.links.internal-link-card.view :as view]
[test-helpers.component :as h]))
(defn- render
[component]
(h/render-with-theme-provider component :light))
(def user-props
{:title "Some title"
:subtitle "Some description"
:loading? false
:icon "data:image/png,logo-x"
:type :user
:customization-color "#ff0000"
:emoji-hash "🌟🚀🐠🌈🏰🔮🦉🐼🍉🎨🚲🌙🍔🌵"})
(h/describe "Internal link card - User"
(h/test "renders with most common props"
(render [view/view user-props])
(h/is-truthy (h/query-by-text (:title user-props)))
(h/is-truthy (h/query-by-text (:subtitle user-props))))
(h/test "does not render logo if prop is not present"
(render [view/view (dissoc user-props :icon)])
(h/is-null (h/query-by-label-text :logo))))
(def community-props
{:title "Some title"
:description "Some description"
:icon "data:image/png,logo-x"
:banner "data:image/png,whatever"
:members-count "20"
:loading? false
:active-members-count "15"
:type :community})
(h/describe "Internal link card - Community"
(h/test "renders with most common props"
(render [view/view community-props])
(h/is-truthy (h/query-by-text (:title community-props)))
(h/is-truthy (h/query-by-text (:description community-props)))
(h/is-truthy (h/query-by-text (:members-count community-props)))
(h/is-truthy (h/query-by-text (:active-members-count community-props)))
(h/is-truthy (h/query-by-label-text :logo))
(h/is-truthy (h/query-by-label-text :thumbnail)))
(h/test "does not render thumbnail if prop is not present"
(render [view/view (dissoc community-props :banner)])
(h/is-null (h/query-by-label-text :thumbnail)))
(h/test "does not render logo if prop is not present"
(render [view/view (dissoc community-props :icon)])
(h/is-null (h/query-by-label-text :logo))))
(def channel-props
{:title "Doodles"
:description "Coloring the world with joy • ᴗ •"
:icon "data:image/png,logo-x"
:banner "data:image/png,whatever"
:loading? false
:channel-name "#general"
:type :channel})
(h/describe "Internal link card - Channel"
(h/test "renders with most common props"
(render [view/view channel-props])
(h/is-truthy (h/query-by-text (:title channel-props)))
(h/is-truthy (h/query-by-text (:description channel-props)))
(h/is-truthy (h/query-by-text (:channel-name channel-props)))
(h/is-truthy (h/query-by-label-text :logo))
(h/is-truthy (h/query-by-label-text :banner)))
(h/test "does not render banner if prop is not present"
(render [view/view (dissoc channel-props :banner)])
(h/is-null (h/query-by-label-text :banner)))
(h/test "does not render logo if prop is not present"
(render [view/view (dissoc channel-props :icon)])
(h/is-null (h/query-by-label-text :logo))))
@@ -1,23 +0,0 @@
(ns quo.components.links.internal-link-card.schema)
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:title {:optional true} [:maybe :string]]
[:description {:optional true} [:maybe :string]]
[:channel-name {:optional true} [:maybe :string]]
[:loading? {:optional true} [:maybe :boolean]]
[:subtitle {:optional true} [:maybe :string]]
[:icon {:optional true} [:maybe [:or :string :int]]]
[:banner {:optional true} [:maybe [:or :string :int]]]
[:type {:optional true} [:maybe :keyword]]
[:on-press {:optional true} [:maybe fn?]]
[:members-count {:optional true} [:maybe [:or :int :string]]]
[:active-members-count {:optional true} [:maybe [:or :int :string]]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:emoji-hash {:optional true} [:maybe :string]]
[:size {:optional true} [:maybe :keyword]]
[:theme :schema.common/theme]]]]
:any])
@@ -1,66 +0,0 @@
(ns quo.components.links.internal-link-card.user.style
(:require [quo.foundations.colors :as colors]))
(defn loading-circle
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:margin-right 4
:width 16
:height 16
:border-radius 16})
(defn loading-first-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 145
:height 16
:border-radius 6})
(defn loading-second-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 112
:height 8
:border-radius 6
:margin-bottom 17})
(defn last-bar-line-bar
[theme]
{:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80 theme)
:width 271
:height 16
:border-radius 6})
(defn gradient-start-color
[customization-color theme]
(colors/theme-colors (colors/resolve-color customization-color theme 10)
(colors/resolve-color customization-color theme 20)
theme))
(defn container
[loading? theme size]
{:border-width 1
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme)
:border-radius 16
:padding-horizontal 12
:padding-top 10
:padding-bottom 12
:height (if loading? 92 110)
:width (if (= :message size) 295 335)})
(def header-container
{:flex-direction :row
:align-items :center})
(def title
{:margin-bottom 2})
(def logo
{:margin-right 6
:width 16
:height 16
:border-radius 8
:margin-bottom 2})
(def row-spacing {:flex-direction :row :margin-bottom 12})
@@ -1,83 +0,0 @@
(ns quo.components.links.internal-link-card.user.view
(:require
[quo.components.links.internal-link-card.schema :as component-schema]
[quo.components.links.internal-link-card.user.style :as style]
[quo.components.markdown.text :as text]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[schema.core :as schema]))
(defn- subtitle-comp
[subtitle emoji-hash]
[rn/view
[text/text
{:size :paragraph-2
:number-of-lines 2
:accessibility-label :subtitle
:style {:margin-bottom 12}}
subtitle]
[rn/view {:style {:flex-direction :row}}
[text/text
{:size :paragraph-2
:number-of-lines 1
:weight :regular
:accessibility-label :emoji-hash}
emoji-hash]]])
(defn- title-comp
[title]
[text/text
{:size :paragraph-1
:number-of-lines 1
:weight :semi-bold
:style style/title
:accessibility-label :title}
title])
(defn- logo-comp
[logo]
[rn/image
{:accessibility-label :logo
:source logo
:style style/logo}])
(defn- loading-view
[theme]
[rn/view {:accessibility-label :loading-user-link-view}
[rn/view {:style style/row-spacing}
[rn/view {:style (style/loading-circle theme)}]
[rn/view {:style (style/loading-first-line-bar theme)}]]
[rn/view {:style (style/loading-second-line-bar theme)}]
[rn/view {:style (style/last-bar-line-bar theme)}]])
(defn- linear-gradient-props
[theme customization-color]
[(style/gradient-start-color customization-color theme) :transparent])
(defn view-internal
[{:keys [title loading? icon
theme on-press subtitle emoji-hash customization-color size]}]
(if loading?
[rn/pressable
{:accessibility-label :internal-link-card
:on-press on-press
:style (style/container loading? theme size)}
[loading-view theme]]
[linear-gradient/linear-gradient
(assoc {:style (style/container loading? theme size)}
:colors
(linear-gradient-props theme customization-color))
[rn/pressable
{:accessibility-label :internal-link-card
:on-press on-press}
[rn/view {:style style/header-container}
(when icon
[logo-comp icon])
[title-comp title]]
(when subtitle
[subtitle-comp subtitle emoji-hash])]]))
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))
@@ -1,11 +0,0 @@
(ns quo.components.links.internal-link-card.view
(:require [quo.components.links.internal-link-card.channel.view :as channel.view]
[quo.components.links.internal-link-card.community.view :as community.view]
[quo.components.links.internal-link-card.user.view :as user.view]))
(defn view
[{card-type :type :as props}]
(case card-type
:community [community.view/view props]
:channel [channel.view/view props]
:user [user.view/view props]))
@@ -47,11 +47,11 @@
(h/render [account/view {:type :tag}])
(h/is-truthy (h/query-by-label-text :tag-container)))
(h/test "renders keycard icon if title-icon is present"
(h/render [account/view {:title-icon :i/placeholder}])
(h/test "renders keycard icon if title-icon? is true"
(h/render [account/view {:title-icon? true}])
(h/is-truthy (h/query-by-label-text :title-icon)))
(h/test "doesn't render keycard icon if title-icon is missing"
(h/test "doesn't render keycard icon if title-icon? is false"
(h/render [account/view])
(h/is-falsy (h/query-by-label-text :title-icon)))
@@ -22,14 +22,14 @@
{:backgroundColor colors/white-opa-5})))
(h/test "on-press-out changes state to :active"
(h/render [address/view {:active-state? true}])
(h/render [address/view])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
{:backgroundColor (colors/custom-color :blue 50 10)})))
(h/test "on-press-out changes state to :active with blur? enabled"
(h/render [address/view {:active-state? true :blur? true}])
(h/render [address/view {:blur? true}])
(h/fire-event :on-press-in (h/get-by-label-text :container))
(h/fire-event :on-press-out (h/get-by-label-text :container))
(h/wait-for #(h/has-style (h/query-by-label-text :container)
@@ -1,24 +0,0 @@
(ns quo.components.list-items.quiz-item.component-spec
(:require
[quo.components.list-items.quiz-item.view :as quiz-item]
[test-helpers.component :as h]))
(h/describe "List Items: Token Value"
(h/test "Number label renders"
(h/render [quiz-item/view
{:state :empty
:word "collapse"
:number 2}])
(h/is-truthy (h/get-by-label-text :number-container)))
(h/test "Success icon renders"
(h/render [quiz-item/view
{:state :success
:word "collapse"
:number 2}])
(h/is-truthy (h/get-by-label-text :success-icon)))
(h/test "Error icon renders"
(h/render [quiz-item/view
{:state :error
:word "collapse"
:number 2}])
(h/is-truthy (h/get-by-label-text :error-icon))))
@@ -1,45 +0,0 @@
(ns quo.components.list-items.quiz-item.style
(:require [quo.foundations.colors :as colors]))
(defn container
[{:keys [blur? theme state]}]
{:flex 1
:flex-direction :row
:justify-content :space-between
:align-items :center
:max-height 56
:padding 12
:border-radius 12
:opacity (if (= state :disabled) 0.3 1)
:border-width (if (and blur? (or (= state :empty) (= state :disabled))) 0 1)
:border-color (case state
:success colors/success-50-opa-20
:error colors/danger-50-opa-20
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme))
:background-color (case state
:empty (if blur?
colors/white-opa-5
(colors/theme-colors colors/white colors/neutral-80-opa-40 theme))
:disabled (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-5 colors/neutral-80-opa-40 theme))
:success (colors/resolve-color :success theme 10)
:error (colors/resolve-color :danger theme 10))})
(defn num-container
[{:keys [blur? theme]}]
{:width 32
:height 32
:justify-content :center
:align-items :center
:border-radius 10
:border-width 1
:border-color (if blur?
colors/white-opa-10
(colors/theme-colors colors/neutral-20 colors/neutral-70 theme))})
(defn text
[{:keys [theme state]}]
{:color (case state
:success (colors/theme-colors colors/success-50 colors/success-60 theme)
:error (colors/theme-colors colors/danger-50 colors/danger-60 theme))})
@@ -1,30 +0,0 @@
(ns quo.components.list-items.quiz-item.view
(:require
[quo.components.icon :as icon]
[quo.components.list-items.quiz-item.style :as style]
[quo.components.markdown.text :as text]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[utils.i18n :as i18n]))
(defn- view-internal
[{:keys [state theme number word] :as props}]
[rn/view {:style (style/container props)}
(if (or (= state :empty) (= state :disabled))
[rn/view
{:style (style/num-container props)
:accessibility-label :number-container}
[text/text {:weight :semi-bold} number]]
[text/text {:style (style/text props)}
(if (= state :success) word (i18n/label :t/oops-wrong-word))])
(when (= state :success)
[icon/icon :i/check
{:color (colors/theme-colors colors/success-50 colors/success-60 theme)
:accessibility-label :success-icon}])
(when (= state :error)
[icon/icon :i/incorrect
{:color (colors/theme-colors colors/danger-50 colors/danger-60 theme)
:accessibility-label :error-icon}])])
(def view (quo.theme/with-theme view-internal))
@@ -26,7 +26,6 @@
(on-press label)))
:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? false)
:hit-slop {:top 8 :bottom 8 :left 25 :right 25}
:style (style/container background-color)}
(case type
:key [icons/icon
+3 -3
View File
@@ -5,7 +5,7 @@
[react-native.core :as rn]))
(defn view
[{:keys [type container-style]} & children]
[{:keys [type]} & children]
[rn/view {:style (style/overlay-background type)}
(if (= type :shell)
[blur/view
@@ -14,7 +14,7 @@
:blur-type :transparent
:overlay-color :transparent
:style style/container}
[rn/view {:style (merge style/blur-container container-style)}
[rn/view {:style style/blur-container}
children]]
[rn/view {:style (merge style/container container-style)}
[rn/view {:style style/container}
children])])
@@ -7,7 +7,14 @@
[utils.datetime :as datetime]))
(h/describe "record audio component"
(h/setup-fake-timers)
(h/before-each
(fn []
(h/use-fake-timers)))
(h/after-each
(fn []
(h/clear-all-timers)
(h/use-real-timers)))
(h/test "renders record-audio"
(h/render [record-audio/record-audio])
@@ -6,7 +6,14 @@
[test-helpers.component :as h]))
(h/describe "soundtrack component"
(h/setup-fake-timers)
(h/before-each
(fn []
(h/use-fake-timers)))
(h/after-each
(fn []
(h/clear-all-timers)
(h/use-real-timers)))
(h/test "renders soundtrack"
(with-redefs [audio/get-player-duration (fn [] 2000)]
@@ -7,20 +7,18 @@
[react-native.core :as rn]))
(defn- category-internal
[{:keys [label data container-style] :as props}]
[rn/view {:style (merge (style/container label) container-style)}
[{:keys [label data] :as props}]
[rn/view {:style (style/container label)}
(when label
[text/text
{:weight :medium
:size :paragraph-2
:style (style/label props)}
label])
[rn/view {:style (style/settings-items props)}
(for [item data]
^{:key item}
[:<>
[settings-item/view item]
(when-not (= item (last data))
[rn/view {:style (style/settings-separator props)}])])]])
[rn/flat-list
{:data data
:style (style/settings-items props)
:render-fn settings-item/view
:separator [rn/view {:style (style/settings-separator props)}]}]])
(def settings-category (quo.theme/with-theme category-internal))
@@ -19,12 +19,10 @@
(defn sub-container
[align-action]
{:flex-direction :row
:padding-right 0.5
:align-items (or align-action :center)})
(defn left-container
[image?]
{:margin-horizontal (if image? 12 0)
(def left-container
{:margin-horizontal 12
:flex 1
:height "100%"
:justify-content :flex-start})
@@ -59,7 +57,6 @@
{:width 15
:height 15
:border-radius 12
:margin-right 4
:background-color background-color})
(def status-tag-container
@@ -109,7 +109,7 @@
:accessibility-label accessibility-label}
[rn/view {:style (style/left-sub-container props)}
[image-component props]
[rn/view {:style (style/left-container (:image props))}
[rn/view {:style style/left-container}
[text/text
{:weight :medium
:style {:color (when blur? colors/white)}} title]
+2 -2
View File
@@ -74,8 +74,8 @@
[rn/view
{:flex-direction :row
:align-items :center}
(for [{:keys [token-icon id]} selected-tokens]
^{:key id}
(for [{:keys [token-icon]} selected-tokens]
^{:key token-icon}
[rn/view {:flex-direction :row}
[rn/view (outer-resource-container size background-color)
[rn/image
@@ -3,13 +3,12 @@
(:require [clojure.string :as string]))
(def ^:private tokens (loader/resolve-tokens))
(def ^:private safe-lower-case (comp string/lower-case str))
(defn- get-token-image*
[token]
(let [token-symbol (cond-> token
(keyword? token) name
:always safe-lower-case)]
:always (comp string/lower-case str))]
(get tokens token-symbol)))
(def get-token-image (memoize get-token-image*))
+7 -8
View File
@@ -37,14 +37,13 @@
(def ^:private b64-png-image-prefix "data:image/png;base64,")
(defn temp-empty-symbol
[token size style]
[token size]
[rn/view
{:style (token-style (merge {:justify-content :center
:align-items :center
:border-radius 20
:border-width 1
:border-color :grey}
style)
{:style (token-style {:justify-content :center
:align-items :center
:border-radius 20
:border-width 1
:border-color :grey}
size)}
[quo/text {:style {:color :grey}}
(some-> token
@@ -74,6 +73,6 @@
[rn/image
{:style (token-style style size)
:source source}]
[temp-empty-symbol token size style])))
[temp-empty-symbol token size])))
(def view (schema/instrument #'view-internal ?schema))
@@ -11,9 +11,8 @@
colors/white))
(defn card
[{:keys [customization-color type theme pressed? metrics?]}]
{:width 161
:height (if metrics? 88 68)
[{:keys [customization-color type theme pressed?]}]
{:width 162
:background-color (when (not= :watch-only type)
(colors/theme-colors
(colors/resolve-color customization-color
@@ -21,8 +21,7 @@
:style (style/card {:customization-color customization-color
:type type
:theme theme
:pressed? false
:metrics? metrics?})}
:pressed? false})}
[rn/view {:style style/loader-container}
[rn/view
{:style (assoc (style/loader-view {:width 16
@@ -114,8 +113,7 @@
:style (style/card {:customization-color customization-color
:type type
:theme theme
:pressed? @pressed?
:metrics? metrics?})
:pressed? @pressed?})
:on-press on-press}
(when (and customization-color (and (not watch-only?) (not missing-keypair?)))
[customization-colors/overlay
@@ -128,13 +126,9 @@
[text/text {:style style/emoji} emoji]]
[rn/view {:style style/watch-only-container}
[text/text
{:size :paragraph-2
:weight :medium
:number-of-lines 1
:max-width 110
:margin-right 4
:ellipis-mode :tail
:style (style/account-name type theme)}
{:size :paragraph-2
:weight :medium
:style (style/account-name type theme)}
name]
(when watch-only? [icon/icon :i/reveal {:color colors/neutral-50 :size 12}])
(when missing-keypair?
@@ -10,7 +10,7 @@
:stored :on-keycard
:derivation-path "m / 44 / 60 / 0 / 0 / 2"
:user-name "Test Name"}])
(-> (h/expect (h/get-by-translation-text :t/origin))
(-> (h/expect (h/get-by-translation-text :origin))
(.toBeTruthy)))
(h/test "recovery phrase icon is visible when :type is :recovery-phrase"
@@ -59,7 +59,7 @@
:stored :on-device
:derivation-path "m / 44 / 60 / 0 / 0 / 2"
:user-name "Test Name"}])
(-> (h/expect (h/get-by-translation-text :t/on-device))
(-> (h/expect (h/get-by-translation-text :on-device))
(.toBeTruthy)))
(h/test "on-keycard text is visible when :stored is :on-keycard"
@@ -68,7 +68,7 @@
:stored :on-keycard
:derivation-path "m / 44 / 60 / 0 / 0 / 2"
:user-name "Test Name"}])
(-> (h/expect (h/get-by-translation-text :t/on-keycard))
(-> (h/expect (h/get-by-translation-text :on-keycard))
(.toBeTruthy)))
(h/test "on-press is called when :type is :recovery-phrase"
@@ -29,7 +29,6 @@
[:checked? {:optional true} [:maybe :boolean]]
[:disabled? {:optional true} [:maybe :boolean]]
[:on-change {:optional true} [:maybe fn?]]
[:container-style {:optional true} [:maybe :map]]
[:theme :schema.common/theme]]]]
:any])
@@ -59,11 +58,11 @@
(defn- view-internal
[{:keys
[checked? disabled? on-change token-details keycard? theme container-style]
[checked? disabled? on-change token-details keycard? theme]
{:keys
[name address emoji customization-color]} :account}]
[rn/view
{:style (merge (style/container theme) container-style)
{:style (style/container theme)
:accessibility-label :wallet-account-permissions}
[rn/view {:style style/row1}
[account-avatar/view
@@ -9,52 +9,48 @@
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn network-bridge-add
[{:keys [network state theme]}]
[rn/view {:style (merge (style/container network state theme) (style/add-container theme))}
[icon/icon :i/add-circle {:size 12 :no-color true}]])
(defn- network->text
[network]
(cond (not network) ""
(= network :ethereum) "Mainnet"
:else (string/capitalize (name network))))
(defn view-internal
[{:keys [theme network status amount container-style] :as args}]
(if (= status :add)
[network-bridge-add args]
[rn/view
{:style (merge (style/container network status theme) container-style)
:accessible true
:accessibility-label :container}
(if (= status :loading)
(let [network-text (if (= network :ethereum) "Mainnet" (string/capitalize (name network)))]
(if (= status :add)
[network-bridge-add args]
[rn/view
{:style (merge (style/container network status theme) container-style)
:accessible true
:accessibility-label :container}
(if (= status :loading)
[rn/view
{:style (style/loading-skeleton theme)
:accessible true
:accessibility-label :loading}]
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[text/text
{:size :paragraph-2
:weight :medium} amount]
(when (= status :locked)
[icon/icon :i/locked
{:size 12
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:accessible true
:accessibility-label :lock}])])
[rn/view
{:style (style/loading-skeleton theme)
:accessible true
:accessibility-label :loading}]
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
{:style {:flex-direction :row
:align-items :center}}
[rn/image
{:source (resources/get-network network)
:style style/network-icon}]
[text/text
{:size :paragraph-2
:weight :medium} amount]
(when (= status :locked)
[icon/icon :i/locked
{:size 12
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:accessible true
:accessibility-label :lock}])])
[rn/view
{:style {:flex-direction :row
:align-items :center}}
[rn/image
{:source (resources/get-network network)
:style style/network-icon}]
[text/text
{:size :label
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
(network->text network)]]]))
{:size :label
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
network-text]]])))
(def view (quo.theme/with-theme view-internal))
@@ -86,10 +86,10 @@
(defn- dashed-line
[network-name]
(into [rn/view {:style style/dashed-line}]
(take 19
(interleave (repeat [rn/view {:style (style/dashed-line-line network-name)}])
(repeat [rn/view {:style style/dashed-line-space}])))))
[rn/view {:style style/dashed-line}
(take 19
(interleave (repeat [rn/view {:style (style/dashed-line-line network-name)}])
(repeat [rn/view {:style style/dashed-line-space}])))])
(defn f-network-routing-bars
[_]
@@ -2,7 +2,6 @@
(:require
[quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
[quo.components.markdown.text :as text]
[quo.components.wallet.summary-info.style :as style]
[quo.foundations.colors :as colors]
@@ -27,29 +26,24 @@
(defn networks
[values theme]
(let [{:keys [ethereum optimism arbitrum]} values
show-optimism? (pos? optimism)
show-arbitrum? (pos? arbitrum)]
(let [{:keys [ethereum optimism arbitrum]} values]
[rn/view
{:style style/networks-container
:accessibility-label :networks}
(when (pos? ethereum)
[network-amount
{:network :ethereum
:amount (str ethereum " ETH")
:divider? (or show-arbitrum? show-optimism?)
:theme theme}])
(when show-optimism?
[network-amount
{:network :optimism
:amount (str optimism " OPT")
:divider? show-arbitrum?
:theme theme}])
(when show-arbitrum?
[network-amount
{:network :arbitrum
:amount (str arbitrum " ARB")
:theme theme}])]))
[network-amount
{:network :ethereum
:amount (str ethereum " ETH")
:divider? true
:theme theme}]
[network-amount
{:network :optimism
:amount (str optimism " ETH")
:divider? true
:theme theme}]
[network-amount
{:network :arbitrum
:amount (str arbitrum " ETH")
:theme theme}]]))
(defn- view-internal
[{:keys [theme type account-props networks? values]}]
@@ -57,13 +51,8 @@
{:style (style/container networks? theme)}
[rn/view
{:style style/info-container}
(case type
:status-account [account-avatar/view account-props]
:saved-account [wallet-user-avatar/wallet-user-avatar (assoc account-props :size :size-32)]
:account [wallet-user-avatar/wallet-user-avatar
(assoc account-props
:size :size-32
:neutral? true)]
(if (= type :status-account)
[account-avatar/view account-props]
[user-avatar/user-avatar account-props])
[rn/view {:style {:margin-left 8}}
(when (not= type :account) [text/text {:weight :semi-bold} (:name account-props)])
@@ -180,8 +180,8 @@
:networks networks}]
[tag-internal tag-photo tag-name tag-number theme]
(for [network networks]
^{:key (:network network)}
(let [assoc-props #(get-network networks %)]
^{:key (:network network)}
[view-network (assoc-props (:network network))]))]])
(def view (quo.theme/with-theme view-internal))
+2 -6
View File
@@ -69,7 +69,6 @@
quo.components.inputs.title-input.view
quo.components.ios.drawer-bar.view
quo.components.keycard.view
quo.components.links.internal-link-card.view
quo.components.links.link-preview.view
quo.components.links.url-preview-list.view
quo.components.links.url-preview.view
@@ -81,7 +80,6 @@
quo.components.list-items.dapp.view
quo.components.list-items.menu-item
quo.components.list-items.preview-list.view
quo.components.list-items.quiz-item.view
quo.components.list-items.saved-address.view
quo.components.list-items.saved-contact-address.view
quo.components.list-items.token-network.view
@@ -289,7 +287,6 @@
(def numbered-keyboard quo.components.numbered-keyboard.numbered-keyboard.view/view)
;;;; Links
(def internal-link-card quo.components.links.internal-link-card.view/view)
(def link-preview quo.components.links.link-preview.view/view)
(def url-preview quo.components.links.url-preview.view/view)
(def url-preview-list quo.components.links.url-preview-list.view/view)
@@ -299,16 +296,15 @@
(def account-list-card quo.components.list-items.account-list-card.view/view)
(def address quo.components.list-items.address.view/view)
(def channel quo.components.list-items.channel.view/view)
(def community-list-item quo.components.list-items.community.view/view)
(def dapp quo.components.list-items.dapp.view/view)
(def menu-item quo.components.list-items.menu-item/menu-item)
(def preview-list quo.components.list-items.preview-list.view/view)
(def quiz-item quo.components.list-items.quiz-item.view/view)
(def user-list quo.components.list-items.user-list/user-list)
(def community-list-item quo.components.list-items.community.view/view)
(def saved-address quo.components.list-items.saved-address.view/view)
(def saved-contact-address quo.components.list-items.saved-contact-address.view/view)
(def token-network quo.components.list-items.token-network.view/view)
(def token-value quo.components.list-items.token-value.view/view)
(def user-list quo.components.list-items.user-list/user-list)
;;;; Loaders
(def skeleton-list quo.components.loaders.skeleton-list.view/view)
+106 -102
View File
@@ -1,103 +1,107 @@
(ns quo.core-spec
(:require
quo.components.avatars.account-avatar.component-spec
quo.components.avatars.user-avatar.component-spec
quo.components.banners.banner.component-spec
quo.components.browser.browser-input.component-spec
quo.components.buttons.button.component-spec
quo.components.buttons.composer-button.component-spec
quo.components.buttons.logout-button.component-spec
quo.components.buttons.predictive-keyboard.component-spec
quo.components.buttons.slide-button.component-spec
quo.components.buttons.wallet-button.component-spec
quo.components.buttons.wallet-ctas.component-spec
quo.components.calendar.calendar-day.component-spec
quo.components.calendar.calendar-year.component-spec
quo.components.calendar.calendar.component-spec
quo.components.calendar.calendar.month-picker.component-spec
quo.components.colors.color-picker.component-spec
quo.components.community.community-stat.component-spec
quo.components.counter.counter.component-spec
quo.components.counter.step.component-spec
quo.components.dividers.divider-label.component-spec
quo.components.dividers.strength-divider.component-spec
quo.components.drawers.action-drawers.component-spec
quo.components.drawers.bottom-actions.component-spec
quo.components.drawers.documentation-drawers.component-spec
quo.components.drawers.drawer-buttons.component-spec
quo.components.drawers.drawer-top.component-spec
quo.components.drawers.permission-context.component-spec
quo.components.dropdowns.dropdown-input.component-spec
quo.components.dropdowns.dropdown.component-spec
quo.components.dropdowns.network-dropdown.component-spec
quo.components.gradient.gradient-cover.component-spec
quo.components.graph.wallet-graph.component-spec
quo.components.inputs.address-input.component-spec
quo.components.inputs.input.component-spec
quo.components.inputs.locked-input.component-spec
quo.components.inputs.profile-input.component-spec
quo.components.inputs.recovery-phrase.component-spec
quo.components.inputs.title-input.component-spec
quo.components.keycard.component-spec
quo.components.links.internal-link-card.component-spec
quo.components.links.link-preview.component-spec
quo.components.links.url-preview-list.component-spec
quo.components.links.url-preview.component-spec
quo.components.list-items.account.component-spec
quo.components.list-items.address.component-spec
quo.components.list-items.channel.component-spec
quo.components.list-items.community.component-spec
quo.components.list-items.dapp.component-spec
quo.components.list-items.quiz-item.component-spec
quo.components.list-items.saved-address.component-spec
quo.components.list-items.saved-contact-address.component-spec
quo.components.list-items.token-network.component-spec
quo.components.list-items.token-value.component-spec
quo.components.loaders.skeleton-list.component-spec
quo.components.markdown.list.component-spec
quo.components.markdown.text-component-spec
quo.components.navigation.top-nav.component-spec
quo.components.notifications.notification.component-spec
quo.components.numbered-keyboard.keyboard-key.component-spec
quo.components.onboarding.small-option-card.component-spec
quo.components.password.tips.component-spec
quo.components.profile.link-card.component-spec
quo.components.profile.select-profile.component-spec
quo.components.profile.showcase-nav.component-spec
quo.components.record-audio.record-audio.component-spec
quo.components.record-audio.soundtrack.component-spec
quo.components.selectors.disclaimer.component-spec
quo.components.selectors.filter.component-spec
quo.components.selectors.reactions-selector.component-spec
quo.components.selectors.selectors.component-spec
quo.components.settings.category.component-spec
quo.components.settings.data-item.component-spec
quo.components.settings.reorder-item.component-spec
quo.components.settings.settings-item.component-spec
quo.components.share.share-qr-code.component-spec
quo.components.switchers.base-card.component-spec
quo.components.switchers.group-messaging-card.component-spec
quo.components.tags.network-tags.component-spec
quo.components.tags.status-tags-component-spec
quo.components.tags.summary-tag.component-spec
quo.components.tags.tiny-tag.component-spec
quo.components.text-combinations.channel-name.component-spec
quo.components.text-combinations.page-top.component-spec
quo.components.text-combinations.username.component-spec
quo.components.wallet.account-card.component-spec
quo.components.wallet.account-origin.component-spec
quo.components.wallet.account-overview.component-spec
quo.components.wallet.account-permissions.component-spec
quo.components.wallet.confirmation-progress.component-spec
quo.components.wallet.keypair.component-spec
quo.components.wallet.network-amount.component-spec
quo.components.wallet.network-bridge.component-spec
quo.components.wallet.network-routing.component-spec
quo.components.wallet.progress-bar.component-spec
quo.components.wallet.required-tokens.component-spec
quo.components.wallet.summary-info.component-spec
quo.components.wallet.token-input.component-spec
quo.components.wallet.transaction-progress.component-spec
quo.components.wallet.transaction-summary.component-spec
quo.components.wallet.wallet-activity.component-spec
quo.components.wallet.wallet-overview.component-spec))
(:require ;; [quo.components.list-items.account.component-spec]
;; [quo.components.list-items.address.component-spec]
;; [quo.components.list-items.saved-address.component-spec]
;; [quo.components.list-items.saved-contact-address.component-spec]
;; [quo.components.list-items.saved-contact-address.component-spec]
;; [quo.components.list-items.token-network.component-spec]
[quo.components.avatars.account-avatar.component-spec]
[quo.components.avatars.user-avatar.component-spec]
[quo.components.banners.banner.component-spec]
[quo.components.browser.browser-input.component-spec]
[quo.components.buttons.button.component-spec]
[quo.components.buttons.composer-button.component-spec]
[quo.components.buttons.logout-button.component-spec]
[quo.components.buttons.predictive-keyboard.component-spec]
[quo.components.buttons.slide-button.component-spec]
[quo.components.buttons.wallet-button.component-spec]
[quo.components.buttons.wallet-ctas.component-spec]
[quo.components.calendar.calendar-day.component-spec]
[quo.components.calendar.calendar-year.component-spec]
[quo.components.calendar.calendar.component-spec]
[quo.components.calendar.calendar.month-picker.component-spec]
[quo.components.colors.color-picker.component-spec]
[quo.components.community.community-stat.component-spec]
[quo.components.counter.counter.component-spec]
[quo.components.counter.step.component-spec]
[quo.components.dividers.divider-label.component-spec]
[quo.components.dividers.strength-divider.component-spec]
[quo.components.drawers.action-drawers.component-spec]
[quo.components.drawers.bottom-actions.component-spec]
[quo.components.drawers.documentation-drawers.component-spec]
[quo.components.drawers.drawer-buttons.component-spec]
[quo.components.drawers.drawer-top.component-spec]
[quo.components.drawers.permission-context.component-spec]
[quo.components.dropdowns.dropdown-input.component-spec]
[quo.components.dropdowns.dropdown.component-spec]
[quo.components.dropdowns.network-dropdown.component-spec]
[quo.components.gradient.gradient-cover.component-spec]
[quo.components.graph.wallet-graph.component-spec]
[quo.components.inputs.input.component-spec]
[quo.components.inputs.locked-input.component-spec]
[quo.components.inputs.profile-input.component-spec]
[quo.components.inputs.recovery-phrase.component-spec]
[quo.components.keycard.component-spec]
[quo.components.links.link-preview.component-spec]
[quo.components.links.url-preview-list.component-spec]
[quo.components.links.url-preview.component-spec]
[quo.components.list-items.channel.component-spec]
[quo.components.list-items.community.component-spec]
[quo.components.list-items.dapp.component-spec]
[quo.components.list-items.token-value.component-spec]
[quo.components.loaders.skeleton-list.component-spec]
[quo.components.markdown.list.component-spec]
[quo.components.markdown.text-component-spec]
[quo.components.navigation.top-nav.component-spec]
[quo.components.notifications.notification.component-spec]
[quo.components.numbered-keyboard.keyboard-key.component-spec]
[quo.components.onboarding.small-option-card.component-spec]
[quo.components.password.tips.component-spec]
[quo.components.profile.link-card.component-spec]
[quo.components.profile.select-profile.component-spec]
[quo.components.profile.showcase-nav.component-spec]
[quo.components.record-audio.record-audio.component-spec]
[quo.components.record-audio.soundtrack.component-spec]
[quo.components.selectors.disclaimer.component-spec]
[quo.components.selectors.filter.component-spec]
[quo.components.selectors.reactions-selector.component-spec]
[quo.components.selectors.selectors.component-spec]
[quo.components.settings.category.component-spec]
[quo.components.settings.data-item.component-spec]
[quo.components.settings.reorder-item.component-spec]
[quo.components.settings.settings-item.component-spec]
[quo.components.share.share-qr-code.component-spec]
[quo.components.switchers.base-card.component-spec]
[quo.components.switchers.group-messaging-card.component-spec]
[quo.components.tags.network-tags.component-spec]
[quo.components.tags.status-tags-component-spec]
[quo.components.tags.summary-tag.component-spec]
[quo.components.tags.tiny-tag.component-spec]
[quo.components.text-combinations.channel-name.component-spec]
[quo.components.text-combinations.page-top.component-spec]
[quo.components.text-combinations.username.component-spec]
[quo.components.wallet.account-card.component-spec]
[quo.components.wallet.account-origin.component-spec]
[quo.components.wallet.account-overview.component-spec]
[quo.components.wallet.account-permissions.component-spec]
[quo.components.wallet.confirmation-progress.component-spec]
[quo.components.wallet.keypair.component-spec]
[quo.components.wallet.network-amount.component-spec]
[quo.components.wallet.network-bridge.component-spec]
[quo.components.wallet.network-routing.component-spec]
[quo.components.wallet.progress-bar.component-spec]
[quo.components.wallet.required-tokens.component-spec]
[quo.components.wallet.summary-info.component-spec]
[quo.components.wallet.token-input.component-spec]
[quo.components.wallet.transaction-progress.component-spec]
[quo.components.wallet.transaction-summary.component-spec]
[quo.components.wallet.wallet-activity.component-spec]
[quo.components.wallet.wallet-overview.component-spec]))
;; [quo.components.inputs.address-input.component-spec]
;; [quo.components.inputs.title-input.component-spec]
;; [quo.components.list-items.account.component-spec]
;; [quo.components.list-items.address.component-spec]
;; [quo.components.list-items.saved-address.component-spec]
;; [quo.components.list-items.saved-contact-address.component-spec]
;; [quo.components.list-items.token-network.component-spec]
-3
View File
@@ -203,9 +203,6 @@
(def danger-50-opa-30 (alpha danger-50 0.3))
(def danger-50-opa-40 (alpha danger-50 0.4))
;;60 with transparency
(def danger-60-opa-10 (alpha danger-60 0.1))
;;;;Warning
(def warning-50 "#FF7D46")
(def warning-60 "#CC6438")
+2 -8
View File
@@ -5,17 +5,11 @@
in non-debug environments.
`value` is first transformed via `malli.core/schema` to make sure we fail fast
and only register valid schemas.
Pass raw schema `value` instead of schema instance when it's `:function` schema
https://github.com/status-im/status-mobile/pull/18364#issuecomment-1875543794"
and only register valid schemas."
[sym value]
`(if ^boolean js/goog.DEBUG
(try
(let [schema-instance# (malli.core/schema ~value)]
(if (and (seq ~value) (= :function (first ~value)))
(malli.core/=> ~sym ~value)
(malli.core/=> ~sym schema-instance#)))
(malli.core/=> ~sym (malli.core/schema ~value))
(catch js/Error e#
(taoensso.timbre/error "Failed to instrument function"
{:symbol ~sym :error e#})
+1 -30
View File
@@ -24,17 +24,11 @@
(defn get-label-by-type
[biometric-type]
(condp = biometric-type
(case biometric-type
:fingerprint (i18n/label :t/biometric-fingerprint)
:FaceID (i18n/label :t/biometric-faceid)
(i18n/label :t/biometric-touchid)))
(defn get-icon-by-type
[biometric-type]
(condp = biometric-type
:FaceID :i/face-id
:i/touch-id))
(re-frame/reg-fx
:biometric/get-supported-biometric-type
(fn []
@@ -132,26 +126,3 @@
{:events [:biometric/authenticate]}
[_ opts]
{:biometric/authenticate opts})
(rf/reg-event-fx
:biometric/on-enable-success
(fn [{:keys [db]} [password]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-biometric)
:dispatch [:keychain/save-password-and-auth-method
{:key-uid key-uid
:masked-password password}]})))
(rf/reg-event-fx
:biometric/enable
(fn [_ [password]]
{:dispatch [:biometric/authenticate
{:on-success #(rf/dispatch [:biometric/on-enable-success password])
:on-fail #(rf/dispatch [:biometric/show-message %])}]}))
(rf/reg-event-fx
:biometric/disable
(fn [{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (assoc db :auth-method constants/auth-method-none)
:keychain/clear-user-password key-uid})))
@@ -1,11 +1,8 @@
(ns status-im.contexts.wallet.data-store
(ns status-im.common.data-store.wallet
(:require
[camel-snake-kebab.core :as csk]
[camel-snake-kebab.extras :as cske]
[clojure.set :as set]
[clojure.string :as string]
[status-im.constants :as constants]
[utils.money :as money]
[utils.number :as utils.number]))
(defn chain-ids-string->set
@@ -51,19 +48,6 @@
(update :testPreferredChainIds chain-ids-set->string)
(dissoc :watch-only?)))
(defn- rpc->balances-per-chain
[token]
(-> token
(update :balances-per-chain update-vals #(update % :raw-balance money/bignumber))
(update :balances-per-chain update-keys (comp utils.number/parse-int name))))
(defn rpc->tokens
[tokens]
(-> tokens
(update-keys name)
(update-vals #(cske/transform-keys csk/->kebab-case %))
(update-vals #(mapv rpc->balances-per-chain %))))
(defn <-rpc
[network]
(-> network
+2 -3
View File
@@ -8,8 +8,8 @@
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.chat.actions.view :as chat-actions]
[status-im.contexts.chat.contacts.drawers.nickname-drawer.view :as nickname-drawer]
[status-im.contexts.communities.actions.chat.view :as communities-chat-actions]
[status-im.contexts.contacts.drawers.nickname-drawer.view :as nickname-drawer]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -95,8 +95,7 @@
:button-text (i18n/label :t/confirm)
:close-button-text (i18n/label :t/cancel)
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/close-and-remove-chat
chat-id])
(hide-sheet-and-dispatch [:chat.ui/close-chat chat-id])
(when inside-chat?
(rf/dispatch [:navigate-back])))}])}]))
@@ -131,7 +131,6 @@
:keychain/clear-user-password
(fn [key-uid]
(keychain/reset-credentials (password-migration-key-name key-uid))
(keychain/reset-credentials (str key-uid "-auth"))
(keychain/reset-credentials key-uid)))
(re-frame/reg-fx
@@ -143,11 +142,6 @@
(.then #(when on-success (on-success)))
(.catch #(when on-error (on-error %))))))
(re-frame/reg-event-fx
:keychain/save-password-and-auth-method
(fn [_ [opts]]
{:keychain/save-password-and-auth-method opts}))
;; NOTE: migrating the plaintext password in the keychain
;; with the hashed one. Added due to the sync onboarding
;; flow, where the password arrives already hashed.
+6 -12
View File
@@ -180,11 +180,6 @@
app-state-listener (.addEventListener rn/app-state "change" set-torch-off-fn)]
#(.remove app-state-listener)))
(defn- navigate-back-handler
[]
(rf/dispatch [:navigate-back])
true)
(defn f-view-internal
[{:keys [title subtitle validate-fn on-success-scan error-message]}]
(let [insets (safe-area/get-insets)
@@ -202,16 +197,15 @@
(boolean (not-empty @qr-view-finder)))
camera-ready-to-scan? (and show-camera?
(not @qr-code-succeed?))]
(rn/use-effect
#(set-listener-torch-off-on-app-inactive torch?))
(rn/use-effect
(fn []
(rn/hw-back-add-listener navigate-back-handler)
(set-listener-torch-off-on-app-inactive torch?)
(when-not @camera-permission-granted?
(permissions/permission-granted?
:camera
#(reset! camera-permission-granted? %)
#(reset! camera-permission-granted? false)))
#(rn/hw-back-remove-listener navigate-back-handler)))
(permissions/permission-granted? :camera
#(reset! camera-permission-granted? %)
#(reset! camera-permission-granted? false)))))
[:<>
[rn/view {:style style/background}]
(when camera-ready-to-scan?
+3 -3
View File
@@ -5,11 +5,11 @@
[legacy.status-im.mailserver.core :as mailserver]
[legacy.status-im.visibility-status-updates.core :as visibility-status-updates]
[status-im.common.pairing.events :as pairing]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview]
[status-im.contexts.chat.messenger.messages.transport.events :as messages.transport]
[status-im.contexts.chat.messages.link-preview.events :as link-preview]
[status-im.contexts.chat.messages.transport.events :as messages.transport]
[status-im.contexts.communities.discover.events]
[status-im.contexts.profile.login.events :as profile.login]
[status-im.contexts.profile.push-notifications.local.events :as local-notifications]
[status-im.contexts.push-notifications.local.events :as local-notifications]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
@@ -6,8 +6,3 @@
(fn [{:keys [db]} [callback]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:keychain/get-user-password [key-uid callback]]]})))
(rf/reg-event-fx
:standard-auth/reset-login-password
(fn [{:keys [db]}]
{:db (update db :profile/login dissoc :password :error)}))

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