Compare commits

..
Author SHA1 Message Date
Icaro Motta 25bf309a8a Example showing working/non-working animation 2023-01-04 19:12:05 -03:00
112 changed files with 1397 additions and 3731 deletions
+11 -13
View File
@@ -1,18 +1,16 @@
{:lint-as {status-im.utils.views/defview clojure.core/defn
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
test-helpers.unit/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
{:lint-as {status-im.utils.views/defview clojure.core/defn
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
status-im.test-helpers/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:consistent-alias {:level :error
:aliases {clojure.string string
clojure.set set
clojure.walk walk
taoensso.timbre log}}
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;; TODO remove number when this is fixed
+1 -1
View File
@@ -364,7 +364,7 @@ actually subscribing to them, so reframe's signal graph gets validated too.
(is (= expected (recipes [current-user all-recipes location]))))))
;; good
(require '[test-helpers.unit :as h])
(require '[status-im.test-helpers :as h])
(re-frame/reg-sub
:user/recipes
@@ -19,11 +19,6 @@ def getStatusGoSHA1 = { ->
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
@@ -59,12 +59,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.Map;
import java.util.Stack;
import java.util.zip.ZipEntry;
@@ -531,33 +527,45 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
StatusThreadPoolExecutor.getInstance().execute(r);
}
private void executeRunnableStatusGoMethod(Supplier<String> method, Callback callback) throws JSONException {
@ReactMethod
public void verify(final String address, final String password, final Callback callback) {
Log.d(TAG, "verify");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = () -> {
String res = method.get();
callback.invoke(res);
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
}
@ReactMethod
public void verify(final String address, final String password, final Callback callback) throws JSONException {
Activity currentActivity = getCurrentActivity();
final String absRootDirPath = this.getNoBackupDirectory();
final String newKeystoreDir = pathCombine(absRootDirPath, "keystore");
executeRunnableStatusGoMethod(() -> Statusgo.verifyAccountPassword(newKeystoreDir, address, password), callback);
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.verifyAccountPassword(newKeystoreDir, address, password);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void verifyDatabasePassword(final String keyUID, final String password, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.verifyDatabasePassword(keyUID, password), callback);
public void verifyDatabasePassword(final String keyUID, final String password, final Callback callback) {
Log.d(TAG, "verifyDatabasePassword");
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.verifyDatabasePassword(keyUID, password);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
public String getKeyStorePath(String keyUID) {
@@ -727,59 +735,209 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void addPeer(final String enode, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.addPeer(enode), callback);
public void addPeer(final String enode, final Callback callback) {
Log.d(TAG, "addPeer");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.addPeer(enode);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountStoreAccount(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreAccount(json), callback);
public void multiAccountStoreAccount(final String json, final Callback callback) {
Log.d(TAG, "multiAccountStoreAccount");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountStoreAccount(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountLoadAccount(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountLoadAccount(json), callback);
public void multiAccountLoadAccount(final String json, final Callback callback) {
Log.d(TAG, "multiAccountLoadAccount");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountLoadAccount(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountReset(final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountReset(), callback);
public void multiAccountReset(final Callback callback) {
Log.d(TAG, "multiAccountReset");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountReset();
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountDeriveAddresses(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountDeriveAddresses(json), callback);
public void multiAccountDeriveAddresses(final String json, final Callback callback) {
Log.d(TAG, "multiAccountDeriveAddresses");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountDeriveAddresses(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountGenerateAndDeriveAddresses(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountGenerateAndDeriveAddresses(json), callback);
public void multiAccountGenerateAndDeriveAddresses(final String json, final Callback callback) {
Log.d(TAG, "multiAccountGenerateAndDeriveAddresses");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountGenerateAndDeriveAddresses(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountStoreDerived(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreDerivedAccounts(json), callback);
public void multiAccountStoreDerived(final String json, final Callback callback) {
Log.d(TAG, "multiAccountStoreDerived");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountStoreDerivedAccounts(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountImportMnemonic(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportMnemonic(json), callback);
public void multiAccountImportMnemonic(final String json, final Callback callback) {
Log.d(TAG, "multiAccountImportMnemonic");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountImportMnemonic(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void multiAccountImportPrivateKey(final String json, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportPrivateKey(json), callback);
public void multiAccountImportPrivateKey(final String json, final Callback callback) {
Log.d(TAG, "multiAccountImportPrivateKey");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiAccountImportPrivateKey(json);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void hashTransaction(final String txArgsJSON, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.hashTransaction(txArgsJSON), callback);
public void hashTransaction(final String txArgsJSON, final Callback callback) {
Log.d(TAG, "hashTransaction");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.hashTransaction(txArgsJSON);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void hashMessage(final String message, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.hashMessage(message), callback);
public void hashMessage(final String message, final Callback callback) {
Log.d(TAG, "hashMessage");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.hashMessage(message);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
@@ -789,7 +947,20 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
final String keyStorePath = this.getKeyStorePath(keyUID);
jsonConfig.put("keystorePath", keyStorePath);
executeRunnableStatusGoMethod(() -> Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString()), callback);
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = new Runnable() {
@Override
public void run() {
String res = Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString());
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
}
@ReactMethod
@@ -798,11 +969,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
final String keyStorePath = pathCombine(this.getNoBackupDirectory(), "/keystore");
jsonConfig.put("keystorePath", keyStorePath);
executeRunnableStatusGoMethod(() -> Statusgo.inputConnectionStringForBootstrapping(connectionString, jsonConfig.toString()), callback);
}
@ReactMethod
public void multiformatSerializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException {
if (!checkAvailability()) {
callback.invoke(false);
return;
@@ -811,7 +977,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
Runnable runnableTask = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiformatSerializePublicKey(multiCodecKey,base58btc);
String res = Statusgo.inputConnectionStringForBootstrapping(connectionString,jsonConfig.toString());
callback.invoke(res);
}
};
@@ -819,117 +985,157 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
}
@ReactMethod
public void multiformatDeserializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException {
public void hashTypedData(final String data, final Callback callback) {
Log.d(TAG, "hashTypedData");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = new Runnable() {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.multiformatDeserializePublicKey(multiCodecKey,base58btc);
String res = Statusgo.hashTypedData(data);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void compressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException {
public void hashTypedDataV4(final String data, final Callback callback) {
Log.d(TAG, "hashTypedDataV4");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = new Runnable() {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.compressPublicKey(multiCodecKey);
String res = Statusgo.hashTypedDataV4(data);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void decompressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException {
public void sendTransactionWithSignature(final String txArgsJSON, final String signature, final Callback callback) {
Log.d(TAG, "sendTransactionWithSignature");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = new Runnable() {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.decompressPublicKey(multiCodecKey);
String res = Statusgo.sendTransactionWithSignature(txArgsJSON, signature);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void deserializeAndCompressKey(final String desktopKey, final Callback callback) throws JSONException {
public void sendTransaction(final String txArgsJSON, final String password, final Callback callback) {
Log.d(TAG, "sendTransaction");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable runnableTask = new Runnable() {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.deserializeAndCompressKey(desktopKey);
String res = Statusgo.sendTransaction(txArgsJSON, password);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void hashTypedData(final String data, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.hashTypedData(data), callback);
public void signMessage(final String rpcParams, final Callback callback) {
Log.d(TAG, "signMessage");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.signMessage(rpcParams);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void hashTypedDataV4(final String data, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.hashTypedDataV4(data), callback);
public void recover(final String rpcParams, final Callback callback) {
Log.d(TAG, "recover");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.recover(rpcParams);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void sendTransactionWithSignature(final String txArgsJSON, final String signature, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.sendTransactionWithSignature(txArgsJSON, signature), callback);
public void signTypedData(final String data, final String account, final String password, final Callback callback) {
Log.d(TAG, "signTypedData");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.signTypedData(data, account, password);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void sendTransaction(final String txArgsJSON, final String password, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.sendTransaction(txArgsJSON, password), callback);
}
public void signTypedDataV4(final String data, final String account, final String password, final Callback callback) {
Log.d(TAG, "signTypedDataV4");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
@ReactMethod
public void signMessage(final String rpcParams, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.signMessage(rpcParams), callback);
}
@ReactMethod
public void recover(final String rpcParams, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.recover(rpcParams), callback);
}
@ReactMethod
public void signTypedData(final String data, final String account, final String password, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.signTypedData(data, account, password), callback);
}
@ReactMethod
public void signTypedDataV4(final String data, final String account, final String password, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.signTypedDataV4(data, account, password), callback);
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.signTypedDataV4(data, account, password);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
@@ -1034,13 +1240,29 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void callRPC(final String payload, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.callRPC(payload), callback);
public void callRPC(final String payload, final Callback callback) {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.callRPC(payload);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void callPrivateRPC(final String payload, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.callPrivateRPC(payload), callback);
public void callPrivateRPC(final String payload, final Callback callback) {
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.callPrivateRPC(payload);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
@@ -1103,30 +1325,105 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void extractGroupMembershipSignatures(final String signaturePairs, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.extractGroupMembershipSignatures(signaturePairs), callback);
public void extractGroupMembershipSignatures(final String signaturePairs, final Callback callback) {
Log.d(TAG, "extractGroupMembershipSignatures");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.extractGroupMembershipSignatures(signaturePairs);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void signGroupMembership(final String content, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.signGroupMembership(content), callback);
public void signGroupMembership(final String content, final Callback callback) {
Log.d(TAG, "signGroupMembership");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.signGroupMembership(content);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void getNodeConfig(final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.getNodeConfig(), callback);
public void getNodeConfig(final Callback callback) {
Log.d(TAG, "getNodeConfig");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.getNodeConfig();
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void deleteMultiaccount(final String keyUID, final Callback callback) throws JSONException {
public void deleteMultiaccount(final String keyUID, final Callback callback) {
Log.d(TAG, "deleteMultiaccount");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
final String keyStoreDir = this.getKeyStorePath(keyUID);
executeRunnableStatusGoMethod(() -> Statusgo.deleteMultiaccount(keyUID, keyStoreDir), callback);
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.deleteMultiaccount(keyUID, keyStoreDir);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void deleteImportedKey(final String keyUID, final String address, final String password, final Callback callback) throws JSONException {
public void deleteImportedKey(final String keyUID, final String address, final String password, final Callback callback) {
Log.d(TAG, "deleteImportedKey");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
final String keyStoreDir = this.getKeyStorePath(keyUID);
executeRunnableStatusGoMethod(() -> Statusgo.deleteImportedKey(address, password, keyStoreDir), callback);
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.deleteImportedKey(address, password, keyStoreDir);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod(isBlockingSynchronousMethod = true)
@@ -1135,8 +1432,24 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void generateAliasAsync(final String seed, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.generateAlias(seed), callback);
public void generateAliasAsync(final String seed, final Callback callback) {
Log.d(TAG, "generateAliasAsync");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.generateAlias(seed);
Log.d(TAG, res);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod(isBlockingSynchronousMethod = true)
@@ -1200,33 +1513,47 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void identiconAsync(final String seed, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.identicon(seed), callback);
public void identiconAsync(final String seed, final Callback callback) {
Log.d(TAG, "identiconAsync");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String res = Statusgo.identicon(seed);
Log.d(TAG, res);
callback.invoke(res);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void generateAliasAndIdenticonAsync(final String seed, final Callback callback) {
Log.d(TAG, "generateAliasAndIdenticonAsync");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Log.d(TAG, "generateAliasAndIdenticonAsync");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String resIdenticon = Statusgo.identicon(seed);
String resAlias = Statusgo.generateAlias(seed);
Runnable r = new Runnable() {
@Override
public void run() {
String resIdenticon = Statusgo.identicon(seed);
String resAlias = Statusgo.generateAlias(seed);
Log.d(TAG, resIdenticon);
Log.d(TAG, resAlias);
callback.invoke(resAlias, resIdenticon);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
Log.d(TAG, resIdenticon);
Log.d(TAG, resAlias);
callback.invoke(resAlias, resIdenticon);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@Override
@@ -1248,8 +1575,24 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void validateMnemonic(final String seed, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.validateMnemonic(seed), callback);
public void validateMnemonic(final String seed, final Callback callback) {
Log.d(TAG, "validateMnemonic");
if (!checkAvailability()) {
callback.invoke(false);
return;
}
Runnable r = new Runnable() {
@Override
public void run() {
String resValidateMnemonic = Statusgo.validateMnemonic(seed);
Log.d(TAG, resValidateMnemonic);
callback.invoke(resValidateMnemonic);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
@@ -1300,14 +1643,35 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
}
@ReactMethod
public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) throws JSONException {
executeRunnableStatusGoMethod(() -> Statusgo.changeDatabasePassword(keyUID, password, newPassword), callback);
public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) {
Log.d(TAG, "reEncryptDbAndKeyStore");
Runnable r = new Runnable() {
@Override
public void run() {
// changes db password and re-encrypts keystore
String result = Statusgo.changeDatabasePassword(keyUID, password, newPassword);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
@ReactMethod
public void convertToKeycardAccount(final String keyUID, final String accountData, final String options, final String password, final String newPassword, final Callback callback) throws JSONException {
public void convertToKeycardAccount(final String keyUID, final String accountData, final String options, final String password, final String newPassword, final Callback callback) {
Log.d(TAG, "convertToKeycardAccount");
final String keyStoreDir = this.getKeyStorePath(keyUID);
executeRunnableStatusGoMethod(() -> Statusgo.convertToKeycardAccount(keyStoreDir, accountData, options, password, newPassword), callback);
Runnable r = new Runnable() {
@Override
public void run() {
String result = Statusgo.convertToKeycardAccount(keyStoreDir, accountData, options, password, newPassword);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
}
@@ -339,38 +339,6 @@ RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs
callback(@[result]);
}
RCT_EXPORT_METHOD(multiformatSerializePublicKey:(NSString *)multiCodecKey
base58btc:(NSString *)base58btc
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoMultiformatSerializePublicKey(multiCodecKey,base58btc);
callback(@[result]);
}
RCT_EXPORT_METHOD(multiformatDeserializePublicKey:(NSString *)multiCodecKey
base58btc:(NSString *)base58btc
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoMultiformatDeserializePublicKey(multiCodecKey,base58btc);
callback(@[result]);
}
RCT_EXPORT_METHOD(decompressPublicKey:(NSString *)multiCodecKey
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoDecompressPublicKey(multiCodecKey);
callback(@[result]);
}
RCT_EXPORT_METHOD(compressPublicKey:(NSString *)multiCodecKey
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoCompressPublicKey(multiCodecKey);
callback(@[result]);
}
RCT_EXPORT_METHOD(deserializeAndCompressKey:(NSString *)desktopKey
callback:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoDeserializeAndCompressKey(desktopKey);
callback(@[result]);
}
RCT_EXPORT_METHOD(hashTypedData:(NSString *)data
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

+1 -1
View File
@@ -83,7 +83,7 @@
:optimizations :simple
:target :node-test
;; When running tests without a REPL you can uncomment below line to `make test-watch` a specific file
;;:ns-regexp "status-im2.subs.subs-test$"
;; :ns-regexp "status-im.chat.models-test$"
:main
status-im.test-runner/main
;; set :ui-driven to true to let shadow-cljs inject node-repl
+78 -5
View File
@@ -1,14 +1,78 @@
(ns i18n.i18n
(:require ["i18n-js" :as i18n]
[clojure.string :as string]
[status-im.goog.i18n :as goog.i18n]))
[status-im.goog.i18n :as goog.i18n]
[react-native.languages :as react-native-languages]))
(defn setup
[default-device-language translations-by-locale]
(def default-device-language (react-native-languages/get-lang-keyword))
(def languages
#{:ar :bn :de :el :en :es :es_419 :es_AR :fil :fr :hi :id :in :it :ja :ko :ms :nl :pl :pt :pt_BR :ru
:tr :vi :zh :zh_Hant :zh_TW})
(defn valid-language
[lang]
(if (contains? languages lang)
(keyword lang)
(let [parts (string/split (name lang) #"[\-\_]")
short-lang (keyword (str (first parts) "_" (second parts)))
shortest-lang (keyword (first parts))]
(if (and (> (count parts) 2) (contains? languages short-lang))
short-lang
(when (contains? languages shortest-lang)
shortest-lang)))))
(defn require-translation
[lang-key]
(when-let [lang (valid-language (keyword lang-key))]
(case lang
:ar (js/require "../translations/ar.json")
:bn (js/require "../translations/bn.json")
:de (js/require "../translations/de.json")
:el (js/require "../translations/el.json")
:en (js/require "../translations/en.json")
:es (js/require "../translations/es.json")
:es_419 (js/require "../translations/es_419.json")
:es_AR (js/require "../translations/es_AR.json")
:fil (js/require "../translations/fil.json")
:fr (js/require "../translations/fr.json")
:hi (js/require "../translations/hi.json")
:id (js/require "../translations/id.json")
:in (js/require "../translations/id.json")
:it (js/require "../translations/it.json")
:ja (js/require "../translations/ja.json")
:ko (js/require "../translations/ko.json")
:ms (js/require "../translations/ms.json")
:nl (js/require "../translations/nl.json")
:pl (js/require "../translations/pl.json")
:pt (js/require "../translations/pt.json")
:pt_BR (js/require "../translations/pt_BR.json")
:ru (js/require "../translations/ru.json")
:tr (js/require "../translations/tr.json")
:vi (js/require "../translations/vi.json")
:zh (js/require "../translations/zh.json")
:zh_Hant (js/require "../translations/zh_hant.json")
:zh_TW (js/require "../translations/zh_TW.json"))))
(def translations-by-locale
(cond-> {:en (require-translation :en)}
(not= :en default-device-language)
(assoc default-device-language
(require-translation (-> (name default-device-language)
(string/replace "-" "_")
keyword)))))
(set! (.-fallbacks i18n) true)
(set! (.-defaultSeparator i18n) "/")
(set! (.-locale i18n) (name default-device-language))
(set! (.-translations i18n) (clj->js translations-by-locale))
(defn init
[]
(set! (.-fallbacks i18n) true)
(set! (.-defaultSeparator i18n) "/")
(set! (.-locale i18n) default-device-language)
(set! (.-translations i18n) translations-by-locale))
(set! (.-locale i18n) (name default-device-language))
(set! (.-translations i18n) (clj->js translations-by-locale)))
(defn get-translations
[]
@@ -70,3 +134,12 @@
(.-locale i18n))
(def format-currency goog.i18n/format-currency)
(defn load-language
[lang loaded-languages]
(when-let [lang-key (valid-language (keyword lang))]
(when-not (contains? @loaded-languages lang-key)
(aset (i18n/get-translations)
lang
(require-translation lang-key))
(swap! loaded-languages conj lang-key))))
+1
View File
@@ -240,6 +240,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
:timing nil
:onChange nil
:View #js {}
:FlatList #js {}
:Image #js {}
:ScrollView #js {}
:Text #js {}
+1 -1
View File
@@ -141,7 +141,7 @@
(if profile-picture
;; display image
[fast-image/fast-image
{:source profile-picture
{:source {:uri profile-picture}
:style (container-styling inner-dimensions outer-dimensions)}]
;; else display initials
[container inner-dimensions outer-dimensions
+3 -4
View File
@@ -32,9 +32,9 @@
:outline {:icon-color colors/neutral-50
:icon-secondary-color colors/neutral-50
:label-color colors/neutral-100
:border-color {:default colors/neutral-30
:border-color {:default colors/neutral-20
:pressed colors/neutral-40
:disabled colors/neutral-30}}
:disabled colors/neutral-20}}
:ghost {:icon-color colors/neutral-50
:icon-secondary-color colors/neutral-50
:label-color colors/neutral-100
@@ -138,8 +138,7 @@
(defn shape-style-container
[type icon size]
{:height size
:border-radius (if (and icon (#{:primary :secondary :danger} type))
{:border-radius (if (and icon (#{:primary :secondary :danger} type))
24
(case size
56 12
@@ -81,21 +81,19 @@
context))))
(defn- activity-message
[{:keys [title body title-number-of-lines body-number-of-lines]}]
[{:keys [title body]}]
[rn/view {:style style/message-container}
(when title
[text/text
{:size :paragraph-2
:accessibility-label :activity-message-title
:style style/message-title
:number-of-lines title-number-of-lines}
:style style/message-title}
title])
(if (string? body)
[text/text
{:style style/message-body
:accessibility-label :activity-message-body
:size :paragraph-1
:number-of-lines body-number-of-lines}
:size :paragraph-1}
body]
body)])
@@ -1,40 +0,0 @@
(ns quo2.components.profile.profile-card.style
(:require [quo2.foundations.colors :as colors]))
(defn card-container
[customization-color]
{:flex-direction :column
:padding 12
:flex 1
:border-radius 16
:background-color (colors/custom-color customization-color 50 40)})
(def card-header
{:flex-direction :row
:justify-content :space-between})
(def name-container
{:flex-direction :row
:margin-top 8
:margin-bottom 2
:align-items :center
:padding-right 12})
(def user-name
{:margin-right 4
:color colors/white})
(def emoji-hash
{:margin-top 10})
(def user-hash
{:color colors/white-opa-60})
(def sign-button
{:margin-top 14})
(def keycard-icon
{:color colors/white-opa-40})
(def option-button
{:background-color colors/white-opa-5})
@@ -1,64 +0,0 @@
(ns quo2.components.profile.profile-card.view
(:require
[quo2.components.profile.profile-card.style :as style]
[quo2.foundations.colors :as colors]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[react-native.core :as rn]))
(defn profile-card
[{:keys [show-sign-profile? key-card? profile-picture name hash customization-color sign-label
emoji-hash on-press-dots on-press-sign show-emoji-hash?]
:or {show-sign-profile? false
show-emoji-hash? false
customization-color :turquoise
key-card? false}}]
[rn/view
{:style (style/card-container customization-color)}
[rn/view
{:style style/card-header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
:override-theme :dark
:size :medium
:status-indicator? false
:ring? true}]
[button/button
{:size 32
:type :blur-bg
:icon true
:override-theme :dark
:style style/option-button
:on-press on-press-dots}
:i/options]]
[rn/view
{:style style/name-container}
[text/text
{:size :heading-2
:weight :semi-bold
:number-of-lines 1
:style style/user-name} name]
(when key-card?
(icon/icon
:i/keycard
style/keycard-icon))]
[text/text
{:weight :monospace
:number-of-lines 1
:style style/user-hash} hash]
(when (and show-emoji-hash? emoji-hash)
[text/text
{:weight :monospace
:number-of-lines 1
:style style/emoji-hash} emoji-hash])
(when show-sign-profile?
[button/button
{:on-press on-press-sign
:type :community
:community-color (colors/custom-color customization-color 60)
:community-text-color colors/white
:style style/sign-button} sign-label])])
+9 -45
View File
@@ -6,6 +6,12 @@
[quo2.theme :as quo2.theme]
[react-native.core :as rn]))
(defn padding-left-for-type
[type]
(case type
:group-avatar 3
8))
(defn trim-public-key
[pk]
(str (subs pk 0 6) "..." (subs pk (- (count pk) 3))))
@@ -24,7 +30,7 @@
:padding-left 8
:background-color (if (= theme :light)
colors/neutral-10
colors/neutral-90)}
colors/neutral-80)}
style)]
children))))
@@ -34,8 +40,7 @@
[base-tag
(-> opts
(select-keys [:override-theme :style])
(assoc-in [:style :padding-left] 3)
(assoc-in [:style :padding-vertical] 2))
(assoc-in [:style :padding-left] 3))
[group-avatar/group-avatar opts]
[text/text
{:weight :medium
@@ -64,7 +69,7 @@
[rn/image
{:style {:width 20
:border-radius 10
:background-color :red
:background-color :white
:height 20}
:source photo}]
[rn/view
@@ -83,44 +88,3 @@
[]
(fn [params username photo]
[context-tag params {:uri photo} username]))
(defn audio-tag
[duration params]
[base-tag
(merge
{:style {:padding-left 2
:padding-vertical 2}}
params)
[rn/view
{:width 20
:height 20
:border-radius 10
:align-items :center
:justify-content :center
:background-color colors/primary-50}
[icons/icon
:i/play
{:color colors/white
:size 12}]]
[text/text
{:weight :medium
:size :paragraph-2
:style {:margin-left 4
:color (colors/theme-colors
colors/neutral-100
colors/white
(:override-theme params))}}
duration]])
(defn community-tag
[avatar community-name params]
[context-tag
(merge
{:style {:padding-vertical 2}
:text-style {:margin-left 2
:color (colors/theme-colors
colors/neutral-100
colors/white
(:override-theme params))}}
params)
avatar community-name])
-6
View File
@@ -52,7 +52,6 @@
quo2.components.tabs.tabs
quo2.components.tags.context-tags
quo2.components.tags.status-tags
quo2.components.profile.profile-card.view
quo2.components.tags.tags))
(def toast quo2.components.notifications.toast/toast)
@@ -75,8 +74,6 @@
(def user-avatar-tag quo2.components.tags.context-tags/user-avatar-tag)
(def context-tag quo2.components.tags.context-tags/context-tag)
(def group-avatar-tag quo2.components.tags.context-tags/group-avatar-tag)
(def audio-tag quo2.components.tags.context-tags/audio-tag)
(def community-tag quo2.components.tags.context-tags/community-tag)
(def tabs quo2.components.tabs.tabs/tabs)
(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs)
(def account-selector quo2.components.tabs.account-selector/account-selector)
@@ -130,9 +127,6 @@
(def notification-dot quo2.components.notifications.notification-dot/notification-dot)
(def count-down-circle quo2.components.notifications.count-down-circle/circle-timer)
;;;; PROFILE
(def profile-card quo2.components.profile.profile-card.view/profile-card)
;;;; SETTINGS
(def privacy-option quo2.components.settings.privacy-option/card)
(def account quo2.components.settings.accounts.view/account)
+1
View File
@@ -24,6 +24,7 @@
(reagent/adapt-react-class (.-TouchableWithoutFeedback ^js react-native)))
(def flat-list flat-list/flat-list)
(def flat-list-animated flat-list/flat-list-animated)
(def section-list section-list/section-list)
+6
View File
@@ -1,8 +1,10 @@
(ns react-native.flat-list
(:require ["react-native" :as react-native]
["react-native-reanimated" :default reanimated]
[reagent.core :as reagent]))
(def react-native-flat-list (reagent/adapt-react-class (.-FlatList ^js react-native)))
(def react-native-flat-list-animated (reagent/adapt-react-class (.-FlatList ^js reanimated)))
(defn- wrap-render-fn
[f render-data]
@@ -39,3 +41,7 @@
(defn flat-list
[props]
[react-native-flat-list (base-list-props props)])
(defn flat-list-animated
[props]
[react-native-flat-list-animated (base-list-props props)])
+18 -13
View File
@@ -1,24 +1,29 @@
(ns react-native.reanimated
(:require ["react-native" :as rn]
(:require ["react-native" :as react-native]
["react-native-linear-gradient" :default LinearGradient]
["react-native-reanimated" :default reanimated :refer
(useSharedValue useAnimatedStyle
withTiming
withDelay
withSpring
withRepeat
Easing
Keyframe
cancelAnimation
SlideInUp
SlideOutUp
LinearTransition)]
(Easing
FadeInLeft
FadeOutRight
Keyframe
LinearTransition
SlideInUp
SlideOutUp
cancelAnimation
useAnimatedStyle
useSharedValue
withDelay
withRepeat
withSpring
withTiming)]
[clojure.string :as string]
[reagent.core :as reagent]))
;; Animations
(def slide-in-up-animation SlideInUp)
(def slide-out-up-animation SlideOutUp)
(def fade-in-left-animation FadeInLeft)
(def fade-out-right-animation FadeOutRight)
(def linear-transition LinearTransition)
;; Animated Components
@@ -26,7 +31,7 @@
(def view (reagent/adapt-react-class (.-View reanimated)))
(def image (reagent/adapt-react-class (.-Image reanimated)))
(def touchable-opacity (create-animated-component (.-TouchableOpacity ^js rn)))
(def touchable-opacity (create-animated-component (.-TouchableOpacity ^js react-native)))
(def linear-gradient (create-animated-component LinearGradient))
+5 -6
View File
@@ -49,9 +49,10 @@
cursor (+ at-sign-idx (count name) 2)]
(rf/merge
cofx
{:db (-> db
(assoc-in [:chats/cursor chat-id] cursor)
(assoc-in [:chats/mention-suggestions chat-id] nil))}
{:db (-> db
(assoc-in [:chats/cursor chat-id] cursor)
(assoc-in [:chats/mention-suggestions chat-id] nil))
:set-text-input-value [chat-id new-text text-input-ref]}
(set-chat-input-text new-text chat-id)
;; NOTE(rasom): Some keyboards do not react on selection property passed to
;; text input (specifically Samsung keyboard with predictive text set on).
@@ -183,11 +184,9 @@
(defn build-image-messages
[{db :db} chat-id]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
album-id (str (random-uuid))]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])]
(mapv (fn [[_ {:keys [uri]}]]
{:chat-id chat-id
:album-id album-id
:content-type constants/content-type-image
:image-path (utils/safe-replace uri #"file://" "")
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
+4 -15
View File
@@ -4,9 +4,9 @@
[status-im.constants :as constants]
[status-im.data-store.chats :as data-store.chats]
[status-im.data-store.messages :as data-store.messages]
[utils.re-frame :as rf]
[status-im2.contexts.activity-center.events :as activity-center]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
[taoensso.timbre :as log]))
(defn cursor->clock-value
[^js cursor]
@@ -101,17 +101,6 @@
:on-success #(re-frame/dispatch
[::mark-all-read-in-community-successful %])}]}))
;; For example, when a user receives a list of 4 image messages while inside the chat screen we
;; shouldn't group the images into albums. When the user exists the chat screen then enters the
;; chat screen again, we now need to group the images into albums (like WhatsApp). The albumize?
;; boolean is used to know whether we need to group these images into albums now or not. The
;; album-id can't be used for this because it will always be there.
(defn mark-album
[message]
(if (:album-id message)
(assoc message :albumize? true)
message))
(rf/defn messages-loaded
"Loads more messages for current chat"
{:events [::messages-loaded]}
@@ -142,8 +131,8 @@
current-clock-value (get-in db
[:pagination-info chat-id
:cursor-clock-value])
clock-value (when cursor (cursor->clock-value cursor))
new-messages (map mark-album new-messages)]
clock-value (when cursor
(cursor->clock-value cursor))]
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
:db (-> db
(update-in [:pagination-info chat-id :cursor-clock-value]
+2 -4
View File
@@ -20,8 +20,7 @@
from
outgoing
whisper-timestamp
deleted-for-me?
albumize?]}]
deleted-for-me?]}]
(-> {:whisper-timestamp whisper-timestamp
:from from
:one-to-one? (= constants/message-type-one-to-one message-type)
@@ -33,8 +32,7 @@
:clock-value clock-value
:type :message
:message-id message-id
:outgoing (boolean outgoing)
:albumize? albumize?}
:outgoing (boolean outgoing)}
add-datemark
add-timestamp))
+11 -11
View File
@@ -1,5 +1,5 @@
(ns status-im.communities.core
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[clojure.string :as string]
[clojure.walk :as walk]
[quo.design-system.colors :as colors]
@@ -28,10 +28,10 @@
(defn <-request-to-join-community-rpc
[r]
(set/rename-keys r
{:communityId :community-id
:publicKey :public-key
:chatId :chat-id}))
(clojure.set/rename-keys r
{:communityId :community-id
:publicKey :public-key
:chatId :chat-id}))
(defn <-requests-to-join-community-rpc
[requests]
@@ -64,12 +64,12 @@
(defn <-rpc
[c]
(-> c
(set/rename-keys {:canRequestAccess :can-request-access?
:canManageUsers :can-manage-users?
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
:canJoin :can-join?
:requestedToJoinAt :requested-to-join-at
:isMember :is-member?})
(clojure.set/rename-keys {:canRequestAccess :can-request-access?
:canManageUsers :can-manage-users?
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
:canJoin :can-join?
:requestedToJoinAt :requested-to-join-at
:isMember :is-member?})
(update :members walk/stringify-keys)
(update :chats <-chats-rpc)
(update :categories <-categories-rpc)))
+1 -18
View File
@@ -205,26 +205,9 @@
(def ^:const community-member-role-manage-users 2)
(def ^:const community-member-role-moderator 3)
(def ^:const local-pairing-connection-string-identifier
(def local-pairing-connection-string-identifier
"If any string begins with cs we know its a connection string.
This is useful when we read QR codes we know it is a connection string if it begins with this identifier.
An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 "
"cs")
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
function at status-go, This key determines the output base of the serialization.
according to https://specs.status.im/spec/2#public-key-serialization we serialize
keys with base58btc encoding"
"z")
(def ^:const deserialization-key
"We pass this deserialization key as a parameter to MultiformatDeserializePublicKey
function at status-go, This key determines the output base of the deserialization.
according to https://specs.status.im/spec/2#public-key-serialization we deserialize
keys with base16 hexadecimal encoding"
"f")
(def ^:const multi-code-prefix
"We prefix our keys with 0xe701 prior to serialisation them"
"0xe701")
+3 -3
View File
@@ -1,5 +1,5 @@
(ns status-im.contact.db
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.ethereum.core :as ethereum]
@@ -68,8 +68,8 @@
(let [current-contact (some->
current-account
(select-keys [:name :preferred-name :public-key :identicon :images])
(set/rename-keys {:name :alias
:preferred-name :name}))
(clojure.set/rename-keys {:name :alias
:preferred-name :name}))
all-contacts (cond-> contacts
current-contact
(assoc public-key current-contact))]
+14 -14
View File
@@ -1,5 +1,5 @@
(ns status-im.data-store.chats
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[status-im.constants :as constants]
[status-im.data-store.messages :as messages]
[utils.re-frame :as rf]
@@ -58,19 +58,19 @@
(defn <-rpc
[chat]
(-> chat
(set/rename-keys {:id :chat-id
:communityId :community-id
:syncedFrom :synced-from
:syncedTo :synced-to
:membershipUpdateEvents :membership-update-events
:deletedAtClockValue :deleted-at-clock-value
:chatType :chat-type
:unviewedMessagesCount :unviewed-messages-count
:unviewedMentionsCount :unviewed-mentions-count
:lastMessage :last-message
:lastClockValue :last-clock-value
:invitationAdmin :invitation-admin
:profile :profile-public-key})
(clojure.set/rename-keys {:id :chat-id
:communityId :community-id
:syncedFrom :synced-from
:syncedTo :synced-to
:membershipUpdateEvents :membership-update-events
:deletedAtClockValue :deleted-at-clock-value
:chatType :chat-type
:unviewedMessagesCount :unviewed-messages-count
:unviewedMentionsCount :unviewed-mentions-count
:lastMessage :last-message
:lastClockValue :last-clock-value
:invitationAdmin :invitation-admin
:profile :profile-public-key})
rpc->type
unmarshal-members
(update :last-message #(when % (messages/<-rpc %)))
+2 -2
View File
@@ -1,12 +1,12 @@
(ns status-im.data-store.contacts
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
(defn <-rpc
[contact]
(-> contact
(set/rename-keys
(clojure.set/rename-keys
{:id :public-key
:ensVerifiedAt :ens-verified-at
:displayName :display-name
+25 -26
View File
@@ -1,5 +1,5 @@
(ns status-im.data-store.messages
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
@@ -10,40 +10,39 @@
(assoc :text (:text content)
:sticker (:sticker content))
:always
(set/rename-keys {:chat-id :chat_id
:whisper-timestamp :whisperTimestamp
:community-id :communityId
:clock-value :clock})))
(clojure.set/rename-keys {:chat-id :chat_id
:whisper-timestamp :whisperTimestamp
:community-id :communityId
:clock-value :clock})))
(defn <-rpc
[message]
(-> message
(set/rename-keys {:id :message-id
:whisperTimestamp :whisper-timestamp
:editedAt :edited-at
:contactVerificationState :contact-verification-state
:contactRequestState :contact-request-state
:commandParameters :command-parameters
:gapParameters :gap-parameters
:messageType :message-type
:localChatId :chat-id
:communityId :community-id
:contentType :content-type
:clock :clock-value
:quotedMessage :quoted-message
:outgoingStatus :outgoing-status
:audioDurationMs :audio-duration-ms
:deleted :deleted?
:deletedForMe :deleted-for-me?
:albumId :album-id
:new :new?})
(clojure.set/rename-keys {:id :message-id
:whisperTimestamp :whisper-timestamp
:editedAt :edited-at
:contactVerificationState :contact-verification-state
:contactRequestState :contact-request-state
:commandParameters :command-parameters
:gapParameters :gap-parameters
:messageType :message-type
:localChatId :chat-id
:communityId :community-id
:contentType :content-type
:clock :clock-value
:quotedMessage :quoted-message
:outgoingStatus :outgoing-status
:audioDurationMs :audio-duration-ms
:deleted :deleted?
:deletedForMe :deleted-for-me?
:new :new?})
(update :quoted-message
set/rename-keys
clojure.set/rename-keys
{:parsedText :parsed-text :communityId :community-id})
(update :outgoing-status keyword)
(update :command-parameters
set/rename-keys
clojure.set/rename-keys
{:transactionHash :transaction-hash
:commandState :command-state})
(assoc :content {:chat-id (:chatId message)
+6 -6
View File
@@ -1,5 +1,5 @@
(ns status-im.data-store.pin-messages
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[status-im.data-store.messages :as messages]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
@@ -8,8 +8,8 @@
[message]
(-> message
(merge (messages/<-rpc (message :message)))
(set/rename-keys {:pinnedAt :pinned-at
:pinnedBy :pinned-by})
(clojure.set/rename-keys {:pinnedAt :pinned-at
:pinnedBy :pinned-by})
(dissoc :message)))
(defn pinned-message-by-chat-id-rpc
@@ -21,9 +21,9 @@
{:json-rpc/call [{:method "wakuext_chatPinnedMessages"
:params [chat-id cursor limit]
:on-success (fn [result]
(let [result (set/rename-keys result
{:pinnedMessages
:pinned-messages})]
(let [result (clojure.set/rename-keys result
{:pinnedMessages
:pinned-messages})]
(on-success (update result :pinned-messages #(map <-rpc %)))))
:on-error on-error}]})
+11 -11
View File
@@ -1,24 +1,24 @@
(ns status-im.data-store.reactions
(:require [clojure.set :as set]))
(:require [clojure.set :as clojure.set]))
(defn ->rpc
[message]
(-> message
(set/rename-keys {:message-id :messageId
:emoji-id :emojiId
:chat-id :localChatId
:message-type :messageType
:emoji-reaction-id :id})))
(clojure.set/rename-keys {:message-id :messageId
:emoji-id :emojiId
:chat-id :localChatId
:message-type :messageType
:emoji-reaction-id :id})))
(defn <-rpc
[message]
(-> message
(dissoc :chat_id)
(set/rename-keys {:messageId :message-id
:localChatId :chat-id
:emojiId :emoji-id
:messageType :message-type
:id :emoji-reaction-id})))
(clojure.set/rename-keys {:messageId :message-id
:localChatId :chat-id
:emojiId :emoji-id
:messageType :message-type
:id :emoji-reaction-id})))
(defn reactions-by-chat-id-rpc
[chat-id
@@ -1,41 +0,0 @@
(ns status-im.data-store.switcher-cards
(:require [clojure.set :as set]
[clojure.walk :as walk]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
(defn <-rpc
[switcher-cards]
(walk/postwalk-replace
{:cardId :card-id
:screenId :screen-id}
switcher-cards))
(defn rpc->
[switcher-card]
(set/rename-keys switcher-card
{:card-id :cardId
:screen-id :screenId}))
(rf/defn upsert-switcher-card-rpc
[_ switcher-card]
{:json-rpc/call [{:method "wakuext_upsertSwitcherCard"
:params [(rpc-> switcher-card)]
:on-success #()
:on-error #()}]})
(rf/defn delete-switcher-card-rpc
[_ card-id]
{:json-rpc/call [{:method "wakuext_deleteSwitcherCard"
:params [card-id]
:on-success #()
:on-error #()}]})
(rf/defn fetch-switcher-cards-rpc
[_]
{:json-rpc/call [{:method "wakuext_switcherCards"
:params []
:on-success #(rf/dispatch
[:shell/switcher-cards-loaded
(:switcherCards ^js %)])
:on-error #(log/error "Failed to fetch switcher cards" %)}]})
@@ -1,18 +1,18 @@
(ns status-im.data-store.visibility-status-updates
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[re-frame.core :as re-frame]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
(defn <-rpc
[visibility-status-update]
(set/rename-keys visibility-status-update
{:publicKey :public-key
:statusType :status-type}))
(clojure.set/rename-keys visibility-status-update
{:publicKey :public-key
:statusType :status-type}))
(defn <-rpc-settings
[settings]
(-> settings
(set/rename-keys
(clojure.set/rename-keys
{:current-user-status :current-user-visibility-status})
(update :current-user-visibility-status <-rpc)))
+1 -3
View File
@@ -9,7 +9,6 @@
[status-im.data-store.chats :as data-store.chats]
[status-im.data-store.invitations :as data-store.invitations]
[status-im.data-store.settings :as data-store.settings]
[status-im.data-store.switcher-cards :as switcher-cards-store]
[status-im.data-store.visibility-status-updates :as visibility-status-updates-store]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
@@ -474,8 +473,7 @@
(multiaccounts/get-profile-picture)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)
(visibility-status-updates-store/fetch-visibility-status-updates-rpc)
(switcher-cards-store/fetch-switcher-cards-rpc))))
(visibility-status-updates-store/fetch-visibility-status-updates-rpc))))
(defn get-new-auth-method
[auth-method save-password?]
+1 -51
View File
@@ -5,8 +5,7 @@
[status-im.utils.platform :as platform]
[status-im.utils.react-native :as react-native-utils]
[status-im.utils.types :as types]
[taoensso.timbre :as log]
[status-im.constants :as constants]))
[taoensso.timbre :as log]))
(defn status
[]
@@ -279,55 +278,6 @@
:connection-string connection-string})
(.inputConnectionStringForBootstrapping ^js (status) connection-string config-json callback))
(defn deserialize-and-compress-key
"Provides a community id (public key) to status-go which is first deserialized
and then compressed. Example input/output :
input key = zQ3shTAten2v9CwyQD1Kc7VXAqNPDcHZAMsfbLHCZEx6nFqk9 and
output key = 0x025596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce6"
[key callback]
(log/info "[native-module] Deserializing and then compressing public key"
{:fn :deserialize-and-compress-key
:key key})
(.deserializeAndCompressKey ^js (status) key callback))
(defn public-key->compressed-key
"Provides public key to status-go and gets back a compressed key via serialization"
[public-key callback]
(let [serialization-key constants/serialization-key
multi-code-prefix constants/multi-code-prefix
multi-code-key (str multi-code-prefix (subs public-key 2))]
(log/info "[native-module] Serializing public key"
{:fn :public-key->compressed-key
:public-key public-key
:multi-code-key multi-code-key})
(.multiformatSerializePublicKey ^js (status) multi-code-key serialization-key callback)))
(defn compressed-key->public-key
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization"
[public-key callback]
(let [deserialization-key constants/deserialization-key]
(log/info "[native-module] Deserializing compressed key"
{:fn :compressed-key->public-key
:public-key public-key})
(.multiformatDeserializePublicKey ^js (status) public-key deserialization-key callback)))
(defn decompress-public-key
"Provides compressed key to status-go and gets back the uncompressed public key"
[public-key callback]
(log/info "[native-module] Decompressing public key"
{:fn :decompress-public-key
:public-key public-key})
(.decompressPublicKey ^js (status) public-key callback))
(defn compress-public-key
"Provides a public key to status-go and gets back a 33bit compressed key back"
[public-key callback]
(log/info "[native-module] Compressing public key"
{:fn :compress-public-key
:public-key public-key})
(.compressPublicKey ^js (status) public-key callback))
(defn hash-typed-data
"used for keycard"
[data callback]
+2 -2
View File
@@ -2,7 +2,7 @@
(:require ["react-native" :as rn]
["react-native-gesture-handler" :refer (gestureHandlerRootHOC)]
["react-native-navigation" :refer (Navigation)]
[clojure.set :as set]
[clojure.set :as clojure.set]
[quo.components.text-input :as quo.text-input]
[quo.design-system.colors :as quo.colors]
[re-frame.core :as re-frame]
@@ -299,7 +299,7 @@
(fn [^js evn]
(let [selected-tab-index (.-selectedTabIndex evn)
comp (get tab-root-ids selected-tab-index)
tab-key (get (set/map-invert tab-key-idx) selected-tab-index)]
tab-key (get (clojure.set/map-invert tab-key-idx) selected-tab-index)]
(re-frame/dispatch [:set :current-tab tab-key])
(when (= @state/root-comp-id comp)
(when (= :chat tab-key)
+1 -2
View File
@@ -63,8 +63,7 @@
:sticker (js/require "../resources/images/mock/sticker.png")
:user-picture-female2 (js/require "../resources/images/mock/user_picture_female2.png")
:user-picture-male4 (js/require "../resources/images/mock/user_picture_male4.png")
:user-picture-male5 (js/require "../resources/images/mock/user_picture_male5.png")
:coinbase (js/require "../resources/images/mock/coinbase.png")})
:user-picture-male5 (js/require "../resources/images/mock/user_picture_male5.png")})
(defn get-theme-image
[k]
+1 -8
View File
@@ -199,12 +199,6 @@
{:type :wallet-account
:account (when account (string/lower-case account))})
(defn community-route-type
[route-params]
(if (string/starts-with? (:community-id route-params) "z")
:desktop-community
:community))
(defn handle-uri
[chain chats uri cb]
(let [{:keys [handler route-params query-params]} (match-uri uri)]
@@ -235,8 +229,7 @@
(cb {:type handler :community-id (:community-id route-params)})
(= handler :community)
(cb {:type (community-route-type route-params)
:community-id (:community-id route-params)})
(cb {:type handler :community-id (:community-id route-params)})
(= handler :community-chat)
(cb {:type handler :chat-id (:chat-id route-params)})
+2 -2
View File
@@ -1,5 +1,5 @@
(ns status-im.signing.core
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
@@ -596,4 +596,4 @@
(sign cofx
{:tx-obj (-> tx
(select-keys [:from :to :value :input :gas :nonce :hash])
(set/rename-keys {:input :data}))})))
(clojure.set/rename-keys {:input :data}))})))
@@ -1,4 +1,4 @@
(ns test-helpers.unit
(ns status-im.test-helpers
(:require [clojure.spec.alpha :as s]
[clojure.string :as string]
[clojure.walk :as walk]))
@@ -34,7 +34,7 @@
Example:
```clojure
(require '[test-helpers.unit :as h])
(require '[status-im.test-helpers :as h])
(h/deftest-sub :wallet/sorted-tokens
[sub-name]
@@ -60,7 +60,7 @@
"Register log fixture which allows inspecting all calls to `taoensso.timbre/log`.
Usage: Simply call this macro once per test namespace, and use the
`test-helpers.unit/logs` atom to deref the collection of all logs for the
`status-im.test-helpers/logs` atom to deref the collection of all logs for the
test under execution.
In Clojure(Script), we can rely on fixtures for each `cljs.deftest`, but not
@@ -69,8 +69,8 @@
[]
`(cljs.test/use-fixtures
:each
{:before test-helpers.unit/log-fixture-before
:after test-helpers.unit/log-fixture-after}))
{:before status-im.test-helpers/log-fixture-before
:after status-im.test-helpers/log-fixture-after}))
(defmacro run-test-sync
"Wrap around `re-frame.test/run-test-sync` to make it work with our aliased
@@ -1,11 +1,11 @@
(ns test-helpers.unit
(ns status-im.test-helpers
"Utilities for simplifying the process of writing tests and improving test
readability.
Avoid coupling this namespace with particularities of the Status' domain, thus
prefer to use it for more general purpose concepts, such as the re-frame event
layer."
(:require-macros test-helpers.unit)
(:require-macros status-im.test-helpers)
(:require [re-frame.core :as rf]
[re-frame.db :as rf-db]
[re-frame.events :as rf-events]
+3 -1
View File
@@ -5,7 +5,9 @@
[shadow.test :as st]
[shadow.test.env :as env]
[utils.re-frame :as rf]
status-im2.setup.i18n-resources))
[i18n.i18n :as i18n]))
(i18n/init)
(defonce repl? (atom false))
@@ -5,7 +5,6 @@
(defn build-message
[{:keys [chat-id
album-id
text
response-to
ens-name
@@ -16,7 +15,6 @@
sticker
content-type]}]
{:chatId chat-id
:albumId album-id
:text text
:responseTo response-to
:ensName ens-name
@@ -4,11 +4,10 @@
[re-frame.core :as re-frame]
[status-im.add-new.db :as db]
[status-im.chat.models :as chat.models]
[i18n.i18n :as i18n]
[status-im.react-native.resources :as resources]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]
[status-im2.setup.i18n-resources :as i18n-resources]
[i18n.i18n :as i18n])
[status-im.ui.components.react :as react])
(:require-macros [status-im.utils.views :as views]))
(defn- start-chat
@@ -74,8 +73,8 @@
(defn get-language-topic
[]
(let [lang (subs (name i18n-resources/default-device-language) 0 2)
lang3 (subs (name i18n-resources/default-device-language) 0 3)
(let [lang (subs (name i18n/default-device-language) 0 2)
lang3 (subs (name i18n/default-device-language) 0 3)
lang-name (or (get lang-names lang3) (get lang-names lang))]
(when-not (= lang "en")
(or lang-name (str "status-" lang)))))
@@ -1,5 +1,5 @@
(ns status-im.ui.screens.communities.reorder-categories
(:require [clojure.set :as set]
(:require [clojure.set :as clojure.set]
[clojure.string :as string]
[clojure.walk :as walk]
[quo.core :as quo]
@@ -48,7 +48,7 @@
[{:keys [id community-id] :as home-item} is-active? drag]
(let [chat-id (string/replace id community-id "")
background-color (if is-active? colors/gray-lighter colors/white)
home-item (set/rename-keys home-item {:id :chat-id})]
home-item (clojure.set/rename-keys home-item {:id :chat-id})]
[rn/view
{:accessibility-label :chat-item
:style (merge styles/category-item
@@ -64,9 +64,14 @@
(i18n/label :t/message-deleted)]])
(defn reply-message
[{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?]}
[{:keys [chat-id id]}
in-chat-input? pin?]
(let [contact-name (rf/sub [:contacts/contact-name-by-identity from])
(let [reply-content-sub (-> [:chats/chat-messages chat-id]
rf/sub
(get id))
{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?]}
reply-content-sub
contact-name (rf/sub [:contacts/contact-name-by-identity from])
current-public-key (rf/sub [:multiaccount/public-key])
content-type (or content-type contentType)]
[rn/view
@@ -175,6 +175,7 @@
:editable (not cooldown-enabled?)
:blur-on-submit false
:auto-focus false
:default-value initial-value
:on-focus #(set-active-panel nil)
:max-length chat.constants/max-text-size
:placeholder-text-color (:text-02 @quo.colors/theme)
@@ -194,14 +195,15 @@
(partial on-change last-text-change timeout-id mentionable-users refs chat-id sending-image)
:on-text-input (partial on-text-input mentionable-users chat-id)}
input-with-mentions (rf/sub [:chat/input-with-mentions])
children (if mentions-enabled?
(map-indexed
(fn [index [type text]]
^{:key (str index "_" type "_" text)}
[rn/text (when (= type :mention) {:style {:color colors/primary-50}})
text])
input-with-mentions)
(get @input-texts chat-id))]
children (fn []
(if mentions-enabled?
(map-indexed
(fn [index [_ text]]
^{:key (str index "_" type "_" text)}
[rn/text (when (= type :mention) {:style {:color colors/primary-50}})
text])
input-with-mentions)
(get @input-texts chat-id)))]
(reset! text-input-ref (:text-input-ref refs))
;when ios implementation for selectable-text-input is ready, we need remove this condition and use
;selectable-text-input directly.
@@ -222,7 +224,8 @@
(defn update-input-text
[{:keys [text-input chat-id]} text]
(on-text-change text chat-id))
(on-text-change text chat-id)
(.setNativeProps ^js text-input (clj->js {:text text})))
(re-frame/reg-fx
:set-text-input-value
@@ -335,7 +338,7 @@
(oops/ocall manager :startActionMode text-input-handle))))
:reagent-render
(fn [chat-id {:keys [style ref on-selection-change] :as props} children]
(fn [_]
(let [ref #(do (reset! text-input-ref %)
(when ref
(quo.react/set-ref-val! ref %)))
@@ -164,7 +164,7 @@
:dy 0 ;used for gesture
:pdy 0 ;used for gesture
:state :min ;:min, :custom-chat-available,
;:custom-chat-unavailable, :max
;:custom-chat-unavailable, :max
:clear false
:minimized-from-handlebar? false})
keyboard-was-shown? (atom false)
@@ -188,19 +188,19 @@
360)
(:top insets)
(:status-bar-height @navigation-const)) ; 360
; -
; default
; height
; -
; default
; height
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56
; -
; top-bar
; height
; -
; top-bar
; height
added-value (if (and (not (seq suggestions))
(or edit reply))
38
0) ; increased height
; of input box
; needed when reply
; of input box
; needed when reply
min-y (+ min-y (when (or edit reply) 38))
bg-opacity (reanimated/use-shared-value 0)
bg-bottom (reanimated/use-shared-value (-
@@ -5,7 +5,7 @@
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[status-im.ui2.screens.chat.pin-limit-popover.style :as style]
[status-im.ui2.screens.chat.pin-limit-popover.style :as style] ;; TODO move to status-im2
[utils.re-frame :as rf]))
;; TODO (flexsurfer) this should be an in-app notification component in quo2
@@ -56,6 +56,6 @@
:right 16}}
[quo/icon :i/close
{:color (colors/theme-colors colors/white colors/neutral-100)
:size 12}]]]))])
:size 8}]]]))])
+2 -18
View File
@@ -14,8 +14,7 @@
[utils.re-frame :as rf]
[status-im.wallet.choose-recipient.core :as choose-recipient]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[status-im.native-module.core :as status]))
[taoensso.timbre :as log]))
;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link
@@ -77,21 +76,7 @@
(rf/defn handle-community
[cofx {:keys [community-id]}]
(log/info "universal-links: handling community" community-id)
(navigation/navigate-to-cofx cofx :community {:community-id community-id})
)
(rf/defn handle-navigation-to-desktop-community-from-mobile
{:events [:handle-navigation-to-desktop-community-from-mobile]}
[{:keys [db]} cofx deserialized-key]
(navigation/navigate-to-cofx cofx :community {:community-id deserialized-key})
)
(rf/defn handle-desktop-community
[cofx {:keys [community-id]}]
(status/deserialize-and-compress-key
community-id
(fn [deserialized-key]
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile cofx (str deserialized-key)]))))
(navigation/navigate-to-cofx cofx :community {:community-id community-id}))
(rf/defn handle-community-chat
[cofx {:keys [chat-id]}]
@@ -160,7 +145,6 @@
:private-chat (handle-private-chat cofx data)
:community-requests (handle-community-requests cofx data)
:community (handle-community cofx data)
:desktop-community (handle-desktop-community cofx data)
:community-chat (handle-community-chat cofx data)
:contact (handle-view-profile cofx data)
:browser (handle-browse cofx data)
+4 -4
View File
@@ -1,5 +1,5 @@
(ns status-im.utils.views
(:require [clojure.walk :as walk]))
(:require [clojure.walk :as w]))
(defn atom?
[sub]
@@ -9,9 +9,9 @@
(defn walk-sub
[sub form->sym]
(if (coll? sub)
(walk/postwalk (fn [f]
(or (form->sym f) f))
sub)
(w/postwalk (fn [f]
(or (form->sym f) f))
sub)
(or (form->sym sub) sub)))
(defn prepare-subs
+2 -2
View File
@@ -1,6 +1,6 @@
(ns status-im.wallet.core
(:require
[clojure.set :as set]
[clojure.set :as clojure.set]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.async-storage.core :as async-storage]
@@ -360,7 +360,7 @@
(rf/merge cofx
(multiaccounts.update/multiaccount-update
:wallet/visible-tokens
(update visible-tokens chain set/union chain-visible-tokens)
(update visible-tokens chain clojure.set/union chain-visible-tokens)
{})
(update-tokens-balances balances)
(prices/update-prices))))
@@ -26,7 +26,7 @@
[quo/text {:style {:margin-left 10}} extra-text]]))
(defn confirmation-drawer
[{:keys [title description context button-text on-press extra-action extra-text accessibility-label]}]
[{:keys [title description context button-text on-press extra-action extra-text]}]
(let [extra-action-selected? (reagent/atom false)]
(fn []
(let [{:keys [group-chat chat-id public-key color name]} context
@@ -38,9 +38,7 @@
id]))
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path id]))]
[rn/view
{:style {:margin-horizontal 20}
:accessibility-label accessibility-label}
[rn/view {:style {:margin-horizontal 20}}
[quo/text
{:weight :semi-bold
:size :heading-1} title]
-20
View File
@@ -13,9 +13,6 @@
(def ^:const content-type-community 9)
(def ^:const content-type-gap 10)
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed
(def ^:const content-type-gif 12)
(def ^:const content-type-link 13)
(def ^:const content-type-album 14)
(def ^:const contact-request-state-none 0)
(def ^:const contact-request-state-mutual 1)
@@ -201,20 +198,3 @@
(def ^:const delete-message-undo-time-limit-ms 4000)
(def ^:const delete-message-for-me-undo-time-limit-ms 4000)
(def ^:const album-image-sizes
{4 {0 146
1 146
2 146
3 146}
5 {0 146
1 146
2 97
3 97
4 97}
:default {0 146
1 146
2 72.5
3 72.5
4 72.5
5 72.5}})
+188 -218
View File
@@ -8,20 +8,19 @@
[utils.re-frame :as rf]))
(defn- entry
[{:keys [icon label on-press danger? sub-label chevron? add-divider? accessibility-label]}]
[{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
{:pre [(keyword? icon)
(string? label)
(fn? on-press)
(boolean? danger?)
(boolean? chevron?)]}
{:icon icon
:label label
:on-press on-press
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)
:add-divider? add-divider?
:accessibility-label accessibility-label})
{:icon icon
:label label
:on-press on-press
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)
:add-divider? add-divider?})
(defn hide-sheet-and-dispatch
[event]
@@ -55,12 +54,11 @@
[:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{:title (i18n/label :t/clear-history?)
:description (i18n/label :t/clear-history-confirmation-content)
:context item
:accessibility-label :clear-history-confirm
:button-text (i18n/label :t/clear-history)
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
{:title (i18n/label :t/clear-history?)
:description (i18n/label :t/clear-history-confirmation-content)
:context item
:button-text (i18n/label :t/clear-history)
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
(defn delete-chat-action
[{:keys [chat-id] :as item}]
@@ -68,12 +66,11 @@
[:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{:title (i18n/label :t/delete-chat?)
:description (i18n/label :t/delete-chat-confirmation)
:context item
:accessibility-label :delete-chat-confirm
:button-text (i18n/label :t/delete-chat)
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
{:title (i18n/label :t/delete-chat?)
:description (i18n/label :t/delete-chat-confirmation)
:context item
:button-text (i18n/label :t/delete-chat)
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
(defn leave-group-action
[item chat-id]
@@ -81,15 +78,14 @@
[:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{:title (i18n/label :t/leave-group?)
:description (i18n/label :t/leave-chat-confirmation)
:context item
:accessibility-label :leave-group
:button-text (i18n/label :t/leave-group)
:on-press #(do
(rf/dispatch [:navigate-back])
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed
chat-id]))}))}]))
{:title (i18n/label :t/leave-group?)
:description (i18n/label :t/leave-chat-confirmation)
:context item
:button-text (i18n/label :t/leave-group)
:on-press #(do
(rf/dispatch [:navigate-back])
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed
chat-id]))}))}]))
(defn block-user-action
[{:keys [public-key] :as item}]
@@ -97,281 +93,255 @@
[:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{:title (i18n/label :t/block-user?)
:description (i18n/label :t/block-contact-details)
:context item
:accessibility-label :block-user
:button-text (i18n/label :t/block-user)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed
public-key])}))}]))
{:title (i18n/label :t/block-user?)
:description (i18n/label :t/block-contact-details)
:context item
:button-text (i18n/label :t/block-user)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed
public-key])}))}]))
(defn mute-chat-entry
[chat-id]
(let [muted? (rf/sub [:chats/muted chat-id])]
(entry {:icon (if muted? :i/muted :i/activity-center)
:label (i18n/label
(if muted?
:unmute-chat
:mute-chat))
:on-press (if muted?
#(unmute-chat-action chat-id)
#(mute-chat-action chat-id))
:danger? false
:accessibility-label :mute-chat
:sub-label nil
:chevron? true})))
(entry {:icon (if muted? :i/muted :i/activity-center)
:label (i18n/label
(if muted?
:unmute-chat
:mute-chat))
:on-press (if muted?
#(unmute-chat-action chat-id)
#(mute-chat-action chat-id))
:danger? false
:sub-label nil
:chevron? true})))
(defn mark-as-read-entry
[chat-id]
(entry {:icon :i/correct
:label (i18n/label :t/mark-as-read)
:on-press #(mark-all-read-action chat-id)
:danger? false
:accessibility-label :mark-as-read
:sub-label nil
:chevron? false
:add-divider? true}))
(entry {:icon :i/correct
:label (i18n/label :t/mark-as-read)
:on-press #(mark-all-read-action chat-id)
:danger? false
:sub-label nil
:chevron? false
:add-divider? true}))
(defn clear-history-entry
[chat-id]
(entry {:icon :i/delete
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
:danger? true
:sub-label nil
:accessibility-label :clear-history
:chevron? false
:add-divider? true}))
(entry {:icon :i/delete
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
:danger? true
:sub-label nil
:chevron? false
:add-divider? true}))
(defn delete-chat-entry
[item]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action item)
:danger? true
:accessibility-label :delete-chat
:sub-label nil
:chevron? false}))
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action item)
:danger? true
:sub-label nil
:chevron? false}))
(defn leave-group-entry
[item extra-data]
(entry
{:icon :i/log-out
:label (i18n/label :t/leave-group)
:on-press #(leave-group-action item (if extra-data (:chat-id extra-data) (:chat-id item)))
:danger? true
:accessibility-label :leave-group
:sub-label nil
:chevron? false
:add-divider? extra-data}))
(entry {:icon :i/log-out
:label (i18n/label :t/leave-group)
:on-press #(leave-group-action item (if extra-data (:chat-id extra-data) (:chat-id item)))
:danger? true
:sub-label nil
:chevron? false
:add-divider? extra-data}))
(defn view-profile-entry
[chat-id]
(entry {:icon :i/friend
:label (i18n/label :t/view-profile)
:on-press #(show-profile-action chat-id)
:danger? false
:accessibility-label :view-profile
:sub-label nil
:chevron? false}))
(entry {:icon :i/friend
:label (i18n/label :t/view-profile)
:on-press #(show-profile-action chat-id)
:danger? false
:sub-label nil
:chevron? false}))
(defn edit-nickname-entry
[chat-id]
(entry {:icon :i/edit
:label (i18n/label :t/edit-nickname)
:on-press #(edit-nickname-action chat-id)
:danger? false
:accessibility-label :edit-nickname
:sub-label nil
:chevron? false}))
(entry {:icon :i/edit
:label (i18n/label :t/edit-nickname)
:on-press #(edit-nickname-action chat-id)
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn edit-name-image-entry
[]
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:accessibility-label :edit-name-and-image
:sub-label nil
:chevron? false}))
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn notifications-entry
[add-divider?]
(entry {:icon :i/notifications
:label (i18n/label :t/notifications)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label "All messages" ; TODO: placeholder
:accessibility-label :manage-notifications
:chevron? true
:add-divider? add-divider?}))
(entry {:icon :i/notifications
:label (i18n/label :t/notifications)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label "All messages" ; TODO: placeholder
:chevron? true
:add-divider? add-divider?}))
;; TODO(OmarBasem): Requires design input.
(defn fetch-messages-entry
[]
(entry {:icon :i/save
:label (i18n/label :t/fetch-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:accessibility-label :fetch-messages
:sub-label nil
:chevron? true}))
(entry {:icon :i/save
:label (i18n/label :t/fetch-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label nil
:chevron? true}))
;; TODO(OmarBasem): Requires design input.
(defn pinned-messages-entry
[]
(entry {:icon :i/pin
:label (i18n/label :t/pinned-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:accessibility-label :pinned-messages
:sub-label nil
:chevron? true}))
(entry {:icon :i/pin
:label (i18n/label :t/pinned-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label nil
:chevron? true}))
(defn remove-from-contacts-entry
[contact]
(entry {:icon :i/remove-user
:label (i18n/label :t/remove-from-contacts)
:on-press #(hide-sheet-and-dispatch [:contact.ui/remove-contact-pressed contact])
:danger? false
:accessibility-label :remove-from-contacts
:sub-label nil
:chevron? false}))
(entry {:icon :i/remove-user
:label (i18n/label :t/remove-from-contacts)
:on-press #(hide-sheet-and-dispatch [:contact.ui/remove-contact-pressed contact])
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn rename-entry
[]
(entry {:icon :i/edit
:label (i18n/label :t/rename)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:accessibility-label :rename-contact
:sub-label nil
:chevron? false}))
(entry {:icon :i/edit
:label (i18n/label :t/rename)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn show-qr-entry
[]
(entry {:icon :i/qr-code
:label (i18n/label :t/show-qr)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:accessibility-label :show-qr-code
:sub-label nil
:chevron? false}))
(entry {:icon :i/qr-code
:label (i18n/label :t/show-qr)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-profile-entry
[]
(entry {:icon :i/share
:label (i18n/label :t/share-profile)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :share-profile
:sub-label nil
:chevron? false}))
(entry {:icon :i/share
:label (i18n/label :t/share-profile)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-group-entry
[]
(entry {:icon :i/share
:label (i18n/label :t/share)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :share-group
:sub-label nil
:chevron? false}))
(entry {:icon :i/share
:label (i18n/label :t/share)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): Requires status-go impl.
(defn mark-untrustworthy-entry
[]
(entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy)
:on-press #(js/alert "TODO: to be implemented, requires status-go impl.")
:danger? true
:accessibility-label :mark-untrustworthy
:sub-label nil
:chevron? false
:add-divider? true}))
(entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy)
:on-press #(js/alert "TODO: to be implemented, requires status-go impl.")
:danger? true
:sub-label nil
:chevron? false
:add-divider? true}))
(defn block-user-entry
[item]
(entry {:icon :i/block
:label (i18n/label :t/block-user)
:on-press #(block-user-action item)
:danger? true
:accessibility-label :block-user
:sub-label nil
:chevron? false}))
(entry {:icon :i/block
:label (i18n/label :t/block-user)
:on-press #(block-user-action item)
:danger? true
:sub-label nil
:chevron? false}))
(defn remove-from-group-entry
[{:keys [public-key]} chat-id]
(let [username (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))]
(entry {:icon :i/placeholder
:label (i18n/label :t/remove-user-from-group {:username username})
:on-press #(hide-sheet-and-dispatch [:group-chats.ui/remove-member-pressed chat-id
public-key true])
:danger? true
:accessibility-label :remove-from-group
:sub-label nil
:chevron? false
:add-divider? true})))
(entry {:icon :i/placeholder
:label (i18n/label :t/remove-user-from-group {:username username})
:on-press #(hide-sheet-and-dispatch [:group-chats.ui/remove-member-pressed chat-id
public-key true])
:danger? true
:sub-label nil
:chevron? false
:add-divider? true})))
(defn group-details-entry
[chat-id]
(entry {:icon :i/members
:label (i18n/label :t/group-details)
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])
:danger? false
:accessibility-label :group-details
:sub-label nil
:chevron? false}))
(entry {:icon :i/members
:label (i18n/label :t/group-details)
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn add-members-entry
[]
(entry {:icon :i/add-user
:label (i18n/label :t/add-members)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :add-members
:sub-label nil
:chevron? false}))
(entry {:icon :i/add-user
:label (i18n/label :t/add-members)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn manage-members-entry
[]
(entry {:icon :i/add-user
:label (i18n/label :t/manage-members)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :manage-members
:sub-label nil
:chevron? false}))
(entry {:icon :i/add-user
:label (i18n/label :t/manage-members)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn edit-group-entry
[]
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :edit-group
:sub-label nil
:chevron? false}))
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn group-privacy-entry
[]
(entry {:icon :i/privacy
:label (i18n/label :t/change-group-privacy)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:accessibility-label :group-privacy
:sub-label nil
:chevron? false}))
(entry {:icon :i/privacy
:label (i18n/label :t/change-group-privacy)
:on-press #(js/alert "TODO: to be implemented")
:danger? false
:sub-label nil
:chevron? false}))
(defn destructive-actions
[{:keys [group-chat] :as item}]
@@ -2,7 +2,7 @@
(:require [cljs.test :refer [deftest is testing]]
[status-im.constants :as constants]
status-im.events
[test-helpers.unit :as h]
[status-im.test-helpers :as h]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.contexts.activity-center.notification-types :as types]
[utils.re-frame :as rf]))
@@ -17,7 +17,7 @@
;; `:chat.ui/navigate-to-chat`, otherwise the chat screen
;; looks completely broken if it has never been opened
;; before for the accepted contact.
[rn/touchable-opacity
[rn/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:contact.ui/send-message-pressed
@@ -9,19 +9,12 @@
[status-im2.contexts.activity-center.notification.mentions.style :as style]
[utils.re-frame :as rf]))
(def tag-params
{:size :small
:override-theme :dark
:color colors/primary-50
:style style/tag
:text-style style/tag-text})
(defn message-body
[message]
(let [parsed-text (get-in message [:content :parsed-text])
parsed-text-children (:children (first parsed-text))]
(into [quo/text
{:number-of-lines 1
{:number-of-lines 2
:style style/tag-text
:accessibility-label :activity-message-body
:size :paragraph-1}]
@@ -36,25 +29,25 @@
parsed-text-children))))
(defn view
[{:keys [author chat-name chat-id message read timestamp]}]
(let [chat (rf/sub [:chats/chat chat-id])
community-id (:community-id chat)
is-chat-from-community? (not (nil? community-id))
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[rn/touchable-opacity
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))}
[quo/activity-log
{:title (i18n/label :t/mention)
:icon :i/mention
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[common/user-avatar-tag author]
[quo/text {:style style/tag-text} (string/lower-case (i18n/label :t/on))]
(if is-chat-from-community?
[quo/context-tag tag-params {:uri community-image} community-name chat-name]
[quo/group-avatar-tag chat-name tag-params])]
:message {:body (message-body message)}}]]))
[{:keys [author chat-name chat-id message] :as notification}]
[rn/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))}
[quo/activity-log
{:title (i18n/label :t/mention)
:icon :i/mention
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:context [[common/user-avatar-tag author]
[quo/text {:style style/tag-text} (string/lower-case (i18n/label :t/on))]
;; TODO (@smohamedjavid): The `group-avatar-tag` component
;; does NOT support displaying channel name along with community/chat name.
;; Need to update the component to support it.
[quo/group-avatar-tag chat-name
{:size :small
:override-theme :dark
:color colors/primary-50
:style style/tag
:text-style style/tag-text}]]
:message {:body (message-body message)}}]])
@@ -1,12 +0,0 @@
(ns status-im2.contexts.activity-center.notification.reply.style
(:require [quo2.foundations.colors :as colors]))
(def tag
{:background-color colors/white-opa-10})
(def tag-text
{:color colors/white})
(def lowercase-text
{:color colors/white
:text-transform :lowercase})
@@ -1,53 +0,0 @@
(ns status-im2.contexts.activity-center.notification.reply.view
(:require [i18n.i18n :as i18n]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[status-im.ui2.screens.chat.messages.message :as old-message]
[status-im2.common.constants :as constants]
[status-im2.contexts.activity-center.notification.common.view :as common]
[status-im2.contexts.activity-center.notification.reply.style :as style]
[utils.datetime :as datetime]
[utils.re-frame :as rf]))
(def tag-params
{:size :small
:override-theme :dark
:color colors/primary-50
:style style/tag
:text-style style/tag-text})
;; NOTE: Replies support text, image and stickers only.
(defn get-message-content
[{:keys [content-type] :as message}]
(case content-type
constants/content-type-text (get-in message [:content :text])
constants/content-type-image [old-message/message-content-image message]
constants/content-type-sticker [old-message/sticker message]))
(defn view
[{:keys [author chat-name chat-id message read timestamp]}]
(let [chat (rf/sub [:chats/chat chat-id])
community-id (:community-id chat)
is-chat-from-community? (not (nil? community-id))
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[rn/touchable-opacity
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))}
[quo/activity-log
{:title (i18n/label :t/message-reply)
:icon :i/reply
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[common/user-avatar-tag author]
[quo/text {:style style/lowercase-text} (i18n/label :t/on)]
(if is-chat-from-community?
[quo/context-tag tag-params {:uri community-image} community-name chat-name]
[quo/group-avatar-tag chat-name tag-params])]
:message {:body-number-of-lines 1
:body (get-message-content message)}}]]))
@@ -3,13 +3,13 @@
[quo.react :as react]
[quo2.core :as quo]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im2.contexts.activity-center.notification-types :as types]
[status-im2.contexts.activity-center.notification.contact-request.view :as contact-request]
[status-im2.contexts.activity-center.notification.contact-verification.view :as
contact-verification]
[status-im2.contexts.activity-center.notification.mentions.view :as mentions]
[status-im2.contexts.activity-center.notification.reply.view :as reply]
[status-im2.contexts.activity-center.style :as style]
[utils.re-frame :as rf]))
@@ -97,7 +97,13 @@
(defn render-notification
[notification index]
[rn/view {:style (style/notification-container index)}
[reanimated/view
{:style (style/notification-container index)
;; The `:layout` property is only necessary when not rendering notifications
;; in a FlatList.
:layout reanimated/linear-transition
:entering (-> ^js reanimated/fade-in-left-animation (.duration 250) (.delay (* index 100)))
:exiting (-> ^js reanimated/fade-out-right-animation (.duration 150))}
(case (:type notification)
types/contact-verification
[contact-verification/view notification {}]
@@ -108,9 +114,6 @@
types/mention
[mentions/view notification]
types/reply
[reply/view notification]
nil)])
(defn view
@@ -124,11 +127,31 @@
window-width (rf/sub [:dimensions/window-width])]
[rn/view {:style (style/screen-container window-width top bottom)}
[header]
[rn/flat-list
{:data notifications
:content-container-style {:flex-grow 1}
:empty-component [empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
:render-fn render-notification}]]))])])
;; Set to true to see insertions/removals causing the layout to
;; animate correctly. When false, the FlatList is not animated at all
;; on layout changes.
;;
;; Issue:
;; https://github.com/software-mansion/react-native-reanimated/issues/2737
(if true
(if (seq notifications)
(map-indexed (fn [index notification]
^{:key (:id notification)}
[render-notification notification index])
notifications)
[empty-tab])
[rn/flat-list-animated
{:data notifications
;; This property seems to be necessary to tell Reanimated which
;; transition to use to animate layout changes. Unfortunately it
;; doesn't work.
;;
;; Comment:
;; https://github.com/software-mansion/react-native-reanimated/issues/2737#issuecomment-1077956272
:item-layout-animation reanimated/linear-transition
:content-container-style {:flex-grow 1}
:empty-component [empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
:render-fn render-notification}])]))])])
@@ -1,22 +0,0 @@
(ns status-im2.contexts.chat.messages.content.album.style
(:require [quo2.foundations.colors :as colors]))
(def album-container
{:flex-direction :row
:flex-wrap :wrap
:overflow :hidden})
(defn image
[size index]
{:width size
:height size
:margin-left (when (and (not= index 0) (not= index 2)) 1)
:margin-bottom (when (< index 2) 1)})
(def overlay
{:position :absolute
:width 73
:height 73
:background-color colors/neutral-80-opa-60
:justify-content :center
:align-items :center})
@@ -1,51 +0,0 @@
(ns status-im2.contexts.chat.messages.content.album.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[status-im2.contexts.chat.messages.content.album.style :as style]
[status-im2.common.constants :as constants]))
(def max-display-count 6)
(defn border-tlr
[index]
(when (= index 0) 12))
(defn border-trr
[index]
(when (= index 1) 12))
(defn border-blr
[index count]
(when (and (= index 2) (> count 2)) 12))
(defn border-brr
[index count]
(when (and (= index (- (min count max-display-count) 1)) (> count 2)) 12))
(defn album-message
[message]
[rn/view
{:style style/album-container}
(map-indexed
(fn [index item]
(let [images-count (count (:album message))
images-size-key (if (< images-count 6) images-count :default)
size (get-in constants/album-image-sizes [images-size-key index])]
[rn/view {:key (:message-id item)}
[fast-image/fast-image
{:style (merge (style/image size index)
{:border-top-left-radius (border-tlr index)
:border-top-right-radius (border-trr index)
:border-bottom-left-radius (border-blr index images-count)
:border-bottom-right-radius (border-brr index images-count)})
:source {:uri (:image (:content item))}}]
(when (and (> images-count max-display-count) (= index (- max-display-count 1)))
[rn/view
{:style (merge style/overlay {:border-bottom-right-radius (border-brr index images-count)})}
[quo/text
{:weight :bold
:size :heading-2
:style {:color colors/white}} (str "+" (- images-count 5))]])]))
(:album message))])
@@ -10,7 +10,6 @@
[status-im2.contexts.chat.messages.content.reactions.view :as reactions]
[status-im2.contexts.chat.messages.content.status.view :as status]
[status-im2.contexts.chat.messages.content.system.text.view :as system.text]
[status-im2.contexts.chat.messages.content.album.view :as album]
[quo2.core :as quo]
[utils.re-frame :as rf]
[status-im.ui2.screens.chat.messages.message :as old-message]
@@ -95,8 +94,6 @@
constants/content-type-audio [not-implemented/not-implemented
[old-message/audio message-data]]
constants/content-type-album [album/album-message message-data]
[not-implemented/not-implemented [content.unknown/unknown-content message-data]])
[status/status message-data]]]]]))
@@ -179,9 +179,7 @@
:on-layout on-messages-view-layout})]
[quo/floating-shell-button
(merge {:jump-to
{:on-press #(do
(rf/dispatch [:close-chat])
(rf/dispatch [:shell/navigate-to-jump-to]))
{:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:label (i18n/label :t/jump-to)}}
(when @show-floating-scroll-down-button
{:scroll-to-bottom {:on-press scroll-to-bottom}}))
@@ -45,13 +45,11 @@
[status-im2.contexts.quo-preview.notifications.activity-logs :as activity-logs]
[status-im2.contexts.quo-preview.notifications.toast :as toast]
[status-im2.contexts.quo-preview.posts-and-attachments.messages-skeleton :as messages-skeleton]
[status-im2.contexts.quo-preview.profile.profile-card :as profile-card]
[status-im2.contexts.quo-preview.reactions.react :as react]
[status-im2.contexts.quo-preview.record-audio.record-audio :as record-audio]
[status-im2.contexts.quo-preview.selectors.disclaimer :as disclaimer]
[status-im2.contexts.quo-preview.selectors.filter :as filter]
[status-im2.contexts.quo-preview.selectors.selectors :as selectors]
[status-im2.contexts.quo-preview.settings.accounts :as accounts]
[status-im2.contexts.quo-preview.settings.privacy-option :as privacy-option]
[status-im2.contexts.quo-preview.switcher.switcher-cards :as switcher-cards]
[status-im2.contexts.quo-preview.tabs.account-selector :as account-selector]
@@ -65,6 +63,7 @@
[status-im2.contexts.quo-preview.wallet.lowest-price :as lowest-price]
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
[status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown]
[status-im2.contexts.quo-preview.settings.accounts :as accounts]
[status-im2.contexts.quo-preview.wallet.token-overview :as token-overview]))
(def screens-categories
@@ -176,9 +175,6 @@
:posts-and-attachments [{:name :messages-skeleton
:insets {:top false}
:component messages-skeleton/preview-messages-skeleton}]
:profile [{:name :profile-card
:insets {:top false}
:component profile-card/preview-profile-card}]
:reactions [{:name :react
:insets {:top false}
:component react/preview-react}]
@@ -108,7 +108,6 @@
:show-cancel false
:style {:border-radius 4
:border-width 1
:color (colors/theme-colors colors/neutral-100 colors/white)
:border-color (colors/theme-colors colors/neutral-100 colors/white)}
:on-change-text #(do
(reset! state* (if (and suffix (> (count %) (count @state*)))
@@ -1,94 +0,0 @@
(ns status-im2.contexts.quo-preview.profile.profile-card
(:require [quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[quo2.core :as quo]
[status-im.react-native.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Show: Sign in to this profile?"
:key :show-sign-profile?
:type :boolean}
{:label "Show: Is from key card?"
:key :key-card?
:type :boolean}
{:label "Show: Emoji hash?"
:key :show-emoji-hash?
:type :boolean}
{:label "Customization Color"
:key :customization-color
:type :select
:options [{:key :primary
:value "Primary"}
{:key :purple
:value "Purple"}
{:key :indigo
:value "Indigo"}
{:key :turquoise
:value "Turquoise"}
{:key :blue
:value "Blue"}
{:key :green
:value "Green"}
{:key :yellow
:value "Yellow"}
{:key :orange
:value "Orange"}
{:key :red
:value "Red"}
{:key :pink
:value "Pink"}
{:key :brown
:value "Brown"}
{:key :beige
:value "Beige"}]}
{:label "Name"
:key :name
:type :text}
{:label "Hash"
:key :hash
:type :text}
{:label "Emoji hash"
:key :emoji-hash
:type :text}
{:label "Sign button label"
:key :sign-label
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom {:show-sign-profile? true
:key-card? true
:name "Matt Grote"
:sign-label "Sign in to this profile"
:on-press-dots nil
:on-press-sign nil
:customization-color :turquoise
:profile-picture (resources/get-mock-image :user-picture-male5)
:show-emoji-hash? true
:hash "zQ3k83euenmcikw7474hfu73t5N"
:emoji-hash "😄😂🫣🍑😇🤢😻🥷🏻🦸🏻‍♀️🦸🏻🦸🏻‍♂️🦹🏻‍♀️🧑🏻‍🎄🎅🏻"})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[rn/view {:flex 1}
[preview/customizer state descriptor]]
[rn/view
{:padding-vertical 60
:flex-direction :row
:margin-horizontal 20
:justify-content :center}
[quo/profile-card @state]]]])))
(defn preview-profile-card
[]
[rn/view
{:background-color (colors/theme-colors colors/white
colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
:keyboardShouldPersistTaps :always
:header [cool-preview]
:key-fn str}]])
@@ -2,7 +2,6 @@
(:require [quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.constants :as constants]
[status-im.react-native.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]
[status-im2.contexts.shell.cards.view :as switcher-cards]
@@ -20,8 +19,6 @@
:value "Group Messaging"}
{:key shell.constants/community-card
:value "Community Card"}
{:key shell.constants/community-channel-card
:value "Community Channel Card"}
{:key shell.constants/browser-card
:value "Browser Card"}
{:key shell.constants/wallet-card
@@ -54,20 +51,26 @@
{:label "Content Type"
:key :content-type
:type :select
:options [{:key constants/content-type-text
:options [{:key :text
:value :text}
{:key constants/content-type-image
{:key :photo
:value :photo}
{:key constants/content-type-sticker
{:key :sticker
:value :sticker}
{:key constants/content-type-gif
{:key :gif
:value :gif}
{:key constants/content-type-audio
{:key :audio
:value :audio}
{:key constants/content-type-community
{:key :community
:value :community}
{:key constants/content-type-link
:value :link}]}
{:key :link
:value :link}
{:key :code
:value :code}
{:key :channel
:value :channel}
{:key :community-info
:value :community-info}]}
{:label "Last Message"
:key :last-message
:type :text}
@@ -87,7 +90,6 @@
(def sticker {:source (resources/get-mock-image :sticker)})
(def community-avatar {:source (resources/get-mock-image :community-logo)})
(def gif {:source (resources/get-mock-image :gif)})
(def coinbase-community (resources/get-mock-image :coinbase))
(def photos-list
[{:source (resources/get-mock-image :photo1)}
@@ -100,27 +102,13 @@
(defn get-mock-content
[data]
(case (:content-type data)
constants/content-type-text
(:last-message data)
constants/content-type-image
photos-list
constants/content-type-sticker
sticker
constants/content-type-gif
gif
constants/content-type-audio
"00:32"
constants/content-type-community
{:avatar coinbase-community
:community-name "Coinbase"}
constants/content-type-link
nil))
:text (:last-message data)
:photo photos-list
:sticker sticker
:gif gif
:channel {:emoji "🍑" :channel-name "# random"}
:community-info {:type :kicked}
(:audio :community :link :code) nil))
(defn get-mock-data
[{:keys [type] :as data}]
@@ -132,19 +120,11 @@
:notification-indicator (:notification-indicator data)
:counter-label (:counter-label data)
:content-type (:content-type data)
:community-channel {:emoji "🍑" :channel-name "# random"}
:community-info {:type :kicked}
:data (get-mock-content data)}}
(case type
shell.constants/one-to-one-chat-card
{:avatar-params {:full-name (:title data)}}
shell.constants/private-group-chat-card
{}
(shell.constants/community-card
shell.constants/community-channel-card)
{:avatar-params community-avatar}
shell.constants/one-to-one-chat-card {:avatar-params {:full-name (:title data)}}
shell.constants/private-group-chat-card {}
shell.constants/community-card {:avatar-params community-avatar}
{})))
(defn cool-preview
@@ -156,7 +136,7 @@
:banner? false
:notification-indicator :counter
:counter-label 2
:content-type constants/content-type-text
:content-type :text
:last-message "This is fantastic! Ethereum"
:preview-label-color colors/white})]
(fn []
@@ -171,7 +151,7 @@
(defn preview-switcher-cards
[]
[rn/view
{:background-color (colors/theme-colors colors/white colors/neutral-90)
{:background-color colors/neutral-100
:flex 1}
[rn/flat-list
{:flex 1
@@ -3,7 +3,6 @@
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.react-native.resources :as resources]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.contexts.quo-preview.preview :as preview]))
@@ -20,8 +19,6 @@
(def example-photo2
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=")
(def coinbase-community (resources/get-mock-image :coinbase))
(def main-descriptor
[{:label "Type"
:key :type
@@ -33,11 +30,7 @@
{:key :group-avatar
:value "Group avatar"}
{:key :context-tag
:value "Context tag"}
{:key :audio
:value "Audio"}
{:key :community
:value "Community"}]}])
:value "Context tag"}]}])
(def context-tag-descriptor
[{:label "Label"
@@ -107,17 +100,13 @@
:public-key
[quo2/public-key-tag {} example-pk]
:avatar
[quo2/user-avatar-tag {} current-username (:photo @state)]
:audio
[quo2/audio-tag "00:32"]
:community
[quo2/community-tag coinbase-community "Coinbase"])]]]))))
[quo2/user-avatar-tag {} current-username (:photo @state)])]]]))))
(defn preview-context-tags
[]
[rn/view
{:background-color (colors/theme-colors colors/white
colors/neutral-95)
colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
+80 -125
View File
@@ -5,85 +5,59 @@
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[status-im2.common.constants :as constants]
[status-im2.contexts.shell.cards.style :as style]
[status-im2.contexts.shell.constants :as shell.constants]))
(defn content-container
[type {:keys [content-type data new-notifications? color-50 community-info community-channel]}]
[{:keys [content-type data new-notifications? color-50]}]
[rn/view {:style (style/content-container new-notifications?)}
(case type
shell.constants/community-card
(case (:type community-info)
:pending [quo/status-tag
{:status {:type :pending}
:label (i18n/label :t/pending)
:size :small
:override-theme :dark}]
:kicked [quo/status-tag
{:status {:type :negative}
:size :small
:override-theme :dark
:label (i18n/label :t/kicked)}]
(:count :permission) [:<>]) ;; Add components for these cases
shell.constants/community-channel-card
[rn/view
{:style {:flex-direction :row
:align-items :center}}
[quo/channel-avatar
{:emoji (:emoji community-channel)
:emoji-background-color (colors/alpha color-50 0.1)}]
[quo/text
{:size :paragraph-2
:weight :medium
:number-of-lines 1
:ellipsize-mode :tail
:style style/community-channel}
(:channel-name community-channel)]]
(case content-type
constants/content-type-text
[quo/text
{:size :paragraph-2
:weight :regular
:number-of-lines 1
:ellipsize-mode :tail
:style style/last-message-text}
data]
constants/content-type-image
[quo/preview-list
{:type :photo
:more-than-99-label (i18n/label :counter-99-plus)
:size 24
:override-theme :dark} data]
constants/content-type-sticker
[fast-image/fast-image
{:source (:source data)
:style style/sticker}]
constants/content-type-gif
[fast-image/fast-image
{:source (:source data)
:style style/gif}]
constants/content-type-audio
[quo/audio-tag data {:override-theme :dark}]
constants/content-type-community
[quo/community-tag
(:avatar data)
(:community-name data)
{:override-theme :dark}]
(constants/content-type-link) ;; Components not available
;; Code snippet content type is not supported yet
[:<>]
nil))])
;; TODO - Use status-im2.common.shell.constants for content type
(case content-type
:text [quo/text
{:size :paragraph-2
:weight :regular
:number-of-lines 1
:ellipsize-mode :tail
:style style/last-message-text}
data]
:photo [quo/preview-list
{:type :photo
:more-than-99-label (i18n/label :counter-99-plus)
:size 24
:override-theme :dark} data]
:sticker [fast-image/fast-image
{:source (:source data)
:style style/sticker}]
:gif [fast-image/fast-image
{:source (:source data)
:style style/gif}]
:channel [rn/view
{:style {:flex-direction :row
:align-items :center}}
[quo/channel-avatar
{:emoji (:emoji data)
:emoji-background-color (colors/alpha color-50 0.1)}]
[quo/text
{:size :paragraph-2
:weight :medium
:number-of-lines 1
:ellipsize-mode :tail
:style style/community-channel}
(:channel-name data)]]
:community-info (case (:type data)
:pending [quo/status-tag
{:status {:type :pending}
:label (i18n/label :t/pending)
:size :small
:override-theme :dark}]
:kicked [quo/status-tag
{:status {:type :negative}
:size :small
:override-theme :dark
:label (i18n/label :t/kicked)}]
(:count :permission) [:<>]) ;; Add components for these cases
(:audio :community :link :code) ;; Components not available
[:<>])])
(defn notification-container
[{:keys [notification-indicator counter-label color-60]}]
@@ -96,9 +70,9 @@
[rn/view {:style (style/unread-dot color-60)}])])
(defn bottom-container
[type {:keys [new-notifications?] :as content}]
[{:keys [new-notifications?] :as content}]
[:<>
[content-container type content]
[content-container content]
(when new-notifications?
[notification-container content])])
@@ -118,8 +92,7 @@
:size :large
:override-theme :dark}]
(shell.constants/community-card
shell.constants/community-channel-card)
shell.constants/community-card
(if (:source avatar-params)
[fast-image/fast-image
{:source (:source avatar-params)
@@ -133,41 +106,19 @@
(string/upper-case (first (:name avatar-params)))]])))
(defn subtitle
[type {:keys [content-type data]}]
(case type
shell.constants/community-card
(i18n/label :t/community)
shell.constants/community-channel-card
(i18n/label :t/community-channel)
(case content-type
constants/content-type-text
(i18n/label :t/message)
constants/content-type-image
(i18n/label
(if (= (count data) 1)
:t/one-photo
:t/n-photos)
{:count (count data)})
constants/content-type-sticker
(i18n/label :t/sticker)
constants/content-type-gif
(i18n/label :t/gif)
constants/content-type-audio
(i18n/label :t/audio-message)
constants/content-type-community
(i18n/label :t/link-to-community)
constants/content-type-link
(i18n/label :t/external-link)
"")))
[{:keys [content-type data]}]
(case content-type
:text (i18n/label :t/message)
:photo (i18n/label :t/n-photos {:count (count data)})
:sticker (i18n/label :t/sticker)
:gif (i18n/label :t/gif)
:audio (i18n/label :t/audio-message)
:community (i18n/label :t/link-to-community)
:link (i18n/label :t/external-link)
:code (i18n/label :t/code-snippet)
:channel (i18n/label :t/community-channel)
:community-info (i18n/label :t/community)
(i18n/label :t/community)))
;; Screens Card
(defn screens-card
@@ -193,8 +144,8 @@
{:size :paragraph-2
:weight :medium
:style style/subtitle}
(subtitle type content)]
[bottom-container type (merge {:color-50 color-50 :color-60 color-60} content)]]
(subtitle content)]
[bottom-container (merge {:color-50 color-50 :color-60 color-60} content)]]
(when avatar-params
[rn/view {:style style/avatar-container}
[avatar avatar-params type customization-color]])
@@ -237,26 +188,30 @@
(defn card
[{:keys [type] :as data}]
(case type
shell.constants/empty-card ;; Placeholder
shell.constants/empty-card ;; Placeholder
[empty-card]
(shell.constants/one-to-one-chat-card ;; Screens Card
shell.constants/private-group-chat-card
shell.constants/community-card
shell.constants/community-channel-card)
shell.constants/one-to-one-chat-card ;; Screens Card
[screens-card data]
shell.constants/browser-card ;; Browser Card
shell.constants/private-group-chat-card ;; Screens Card
[screens-card data]
shell.constants/community-card ;; Screens Card
[screens-card data]
shell.constants/browser-card ;; Browser Card
[browser-card data]
shell.constants/wallet-card ;; Wallet Card
shell.constants/wallet-card ;; Wallet Card
[wallet-card data]
shell.constants/wallet-collectible ;; Wallet Card
shell.constants/wallet-collectible ;; Wallet Card
[wallet-collectible data]
shell.constants/wallet-graph ;; Wallet Card
shell.constants/wallet-graph ;; Wallet Card
[wallet-graph data]
shell.constants/communities-discover ;; Home Card
shell.constants/communities-discover ;; Home Card
[communities-discover data]))
+5 -6
View File
@@ -60,9 +60,8 @@
(def ^:const one-to-one-chat-card 1)
(def ^:const private-group-chat-card 2)
(def ^:const community-card 3)
(def ^:const community-channel-card 4)
(def ^:const browser-card 5)
(def ^:const wallet-card 6)
(def ^:const wallet-collectible 7)
(def ^:const wallet-graph 8)
(def ^:const communities-discover 9)
(def ^:const browser-card 4)
(def ^:const wallet-card 5)
(def ^:const wallet-collectible 6)
(def ^:const wallet-graph 7)
(def ^:const communities-discover 8)
+42 -58
View File
@@ -1,12 +1,10 @@
(ns status-im2.contexts.shell.events
(:require [utils.re-frame :as rf]
[re-frame.core :as re-frame]
[status-im.utils.core :as utils]
(:require [re-frame.core :as re-frame]
[status-im2.common.constants :as constants]
[status-im2.navigation.events :as navigation]
[status-im2.contexts.shell.animation :as animation]
[status-im2.contexts.shell.constants :as shell.constants]
[status-im.data-store.switcher-cards :as switcher-cards-store]))
[status-im2.navigation.events :as navigation]
[utils.re-frame :as rf]))
;; Effects
@@ -31,76 +29,62 @@
;; Events
(rf/defn switcher-cards-loaded
{:events [:shell/switcher-cards-loaded]}
[{:keys [db]} loaded-switcher-cards]
{:db (assoc db
:shell/switcher-cards
(utils/index-by :card-id (switcher-cards-store/<-rpc loaded-switcher-cards)))})
(defn calculate-card-data
[db now view-id id]
(rf/defn add-switcher-card
{:events [:shell/add-switcher-card]}
[{:keys [db now] :as cofx} view-id id]
(case view-id
:chat
(let [chat (get-in db [:chats id])]
(case (:chat-type chat)
constants/one-to-one-chat-type
{:navigate-from :chats-stack
:card-id id
:switcher-card {:type shell.constants/one-to-one-chat-card
:card-id id
:clock now
:screen-id id}}
{:shell/navigate-from-shell-fx :chats-stack
:db (assoc-in
db
[:shell/switcher-cards id]
{:type shell.constants/one-to-one-chat-card
:id id
:clock now})}
constants/private-group-chat-type
{:navigate-from :chats-stack
:card-id id
:switcher-card {:type shell.constants/private-group-chat-card
:card-id id
:clock now
:screen-id id}}
{:shell/navigate-from-shell-fx :chats-stack
:db (assoc-in
db
[:shell/switcher-cards id]
{:type shell.constants/private-group-chat-card
:id id
:clock now})}
constants/community-chat-type
{:navigate-from :communities-stack
:card-id (:community-id chat)
:switcher-card {:type shell.constants/community-channel-card
:card-id (:community-id chat)
:clock now
:screen-id (:chat-id chat)}}
{:shell/navigate-from-shell-fx :communities-stack
:db (assoc-in
db
[:shell/switcher-cards (:community-id chat)]
{:type shell.constants/community-card
:id (:community-id chat)
:clock now
:content {:content-type :channel
:data {:emoji (:emoji chat)
:channel-id (:chat-id chat)
:channel-name (:chat-name
chat)}}})}
nil))
:community
{:navigate-from :communities-stack
:card-id (:community-id id)
:switcher-card {:type shell.constants/community-card
:card-id (:community-id id)
:clock now
:screen-id (:community-id id)}}
nil))
{:shell/navigate-from-shell-fx :communities-stack
:db (assoc-in
db
[:shell/switcher-cards (:community-id id)]
{:type shell.constants/community-card
:id (:community-id id)
:clock now})}
(rf/defn add-switcher-card
{:events [:shell/add-switcher-card]}
[{:keys [db now] :as cofx} view-id id]
(let [card-data (calculate-card-data db now view-id id)
switcher-card (:switcher-card card-data)]
(when card-data
(rf/merge
cofx
{:db (assoc-in
db
[:shell/switcher-cards (:card-id card-data)]
switcher-card)
:shell/navigate-from-shell-fx (:navigate-from card-data)}
(switcher-cards-store/upsert-switcher-card-rpc switcher-card)))))
nil))
(rf/defn close-switcher-card
{:events [:shell/close-switcher-card]}
[{:keys [db] :as cofx} card-id]
(rf/merge
cofx
{:db (update db :shell/switcher-cards dissoc card-id)}
(switcher-cards-store/delete-switcher-card-rpc card-id)))
[{:keys [db]} id]
{:db (update-in db [:shell/switcher-cards] dissoc id)})
(rf/defn navigate-to-jump-to
{:events [:shell/navigate-to-jump-to]}
+3 -7
View File
@@ -51,13 +51,9 @@
:accessibility-label :shell-placeholder-view})
(def placeholder-image
{:margin-top 186
:width 120
:height 120
;; Code to remove once placeholder image/vector will be available
:border-width 5
:border-radius 10
:border-color :red})
{:margin-top 186
:width 120
:height 120})
(def placeholder-title
{:margin-top 20
+8 -7
View File
@@ -47,19 +47,20 @@
(i18n/label :t/jump-to)])
(defn render-card
[{:keys [type screen-id] :as card}]
[{:keys [id type content] :as card}]
(let [card-data (case type
shell.constants/one-to-one-chat-card
(rf/sub [:shell/one-to-one-chat-card screen-id])
(rf/sub [:shell/one-to-one-chat-card id])
shell.constants/private-group-chat-card
(rf/sub [:shell/private-group-chat-card screen-id])
(rf/sub [:shell/private-group-chat-card id])
shell.constants/community-card
(rf/sub [:shell/community-card screen-id])
shell.constants/community-channel-card
(rf/sub [:shell/community-channel-card screen-id])
(if content
(rf/sub [:shell/community-channel-card
id (get-in content [:data :channel-id])
content])
(rf/sub [:shell/community-card id]))
nil)]
[switcher-cards/card (merge card card-data)]))
+2 -1
View File
@@ -10,7 +10,8 @@
[status-im2.navigation.state :as state]
[status-im2.navigation.view :as views]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
[utils.re-frame :as rf] ;; TODO (14/11/22 flexsurfer) move to status-im2 namespace
))
;; REGISTER COMPONENT (LAZY)
(defn reg-comp
+2 -1
View File
@@ -12,7 +12,8 @@
[status-im.ui.screens.signing.views :as signing]
[status-im.ui.screens.wallet-connect.session-proposal.views :as wallet-connect]
[status-im.ui.screens.wallet.send.views :as wallet.send.views]
[status-im2.common.toasts.view :as toasts]
[status-im2.common.toasts.view :as toasts] ;; TODO (14/11/22 flexsurfer) move to status-im2
;; namespace
[status-im2.navigation.screens :as screens]
[status-im2.setup.config :as config]
[status-im2.setup.hot-reload :as reloader]))
+2 -1
View File
@@ -1,6 +1,7 @@
(ns status-im2.setup.config
(:require [clojure.string :as string]
[react-native.config :as react-native-config]
[react-native.config :as react-native-config] ;; TODO (14/11/22 flexsurfer move to status-im2
;; namespace
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens]))
+10 -5
View File
@@ -1,7 +1,6 @@
(ns status-im2.setup.core
(:require
[i18n.i18n :as i18n]
[status-im2.setup.i18n-resources :as i18n-resources]
[re-frame.core :as re-frame]
[re-frame.interop :as interop]
[react-native.core :as rn]
@@ -14,7 +13,8 @@
[status-im.native-module.core :as status]
[status-im.notifications.local :as notifications]
[status-im.utils.universal-links.core :as utils.universal-links]
[status-im2.contexts.shell.animation :as animation]
[status-im2.contexts.shell.animation :as animation] ;; TODO (14/11/22 flexsurfer move to
;; status-im2 namespace
status-im2.contexts.syncing.events
status-im2.navigation.core
[status-im2.setup.config :as config]
@@ -22,6 +22,7 @@
status-im2.setup.events
status-im2.setup.datetime
[status-im2.setup.global-error :as global-error]
[status-im2.setup.i18n-resources :as i18n-resources]
[status-im2.setup.log :as log]
status-im2.subs.root))
@@ -31,15 +32,19 @@
(defn init
[]
(log/setup config/log-level)
(global-error/register-handler)
(when platform/android?
(status/set-soft-input-mode status/adjust-resize))
(notifications/listen-notifications)
(.addEventListener rn/app-state "change" #(re-frame/dispatch [:app-state-change %]))
(react-native-languages/add-change-listener #(fn [lang]
(i18n/set-language lang)
(i18n-resources/load-language lang)))
(i18n/init)
(react-native-languages/add-change-listener
#(fn [lang]
(i18n/load-language lang i18n-resources/loaded-languages)
(i18n/set-language lang)))
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
(utils.universal-links/initialize)
+1 -1
View File
@@ -1,5 +1,5 @@
(ns status-im2.setup.db
(:require [react-native.core :as rn]
(:require [react-native.core :as rn] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
[status-im.fleet.core :as fleet]
[status-im.wallet.db :as wallet.db]
[status-im2.contexts.activity-center.events :as activity-center]))
+1 -1
View File
@@ -2,7 +2,7 @@
(:require [clojure.string :as string]
[quo.theme :as quo.theme]
[quo2.theme :as quo2.theme]
[re-frame.core :as re-frame]
[re-frame.core :as re-frame] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
[status-im.multiaccounts.login.core :as multiaccounts.login]
[status-im.native-module.core :as status]
[status-im.utils.keychain.core :as keychain]
+2 -74
View File
@@ -1,78 +1,6 @@
(ns status-im2.setup.i18n-resources
(:require [clojure.string :as string]
[i18n.i18n :as i18n]
[react-native.languages :as react-native-languages]))
(def default-device-language (react-native-languages/get-lang-keyword))
(def languages
#{:ar :bn :de :el :en :es :es_419 :es_AR :fil :fr :hi :id :in :it :ja :ko :ms :nl :pl :pt :pt_BR :ru
:tr :vi :zh :zh_Hant :zh_TW})
(:require [i18n.i18n :as i18n]))
(defonce loaded-languages
(atom
(conj #{:en} default-device-language)))
(defn valid-language
[lang]
(if (contains? languages lang)
(keyword lang)
(let [parts (string/split (name lang) #"[\-\_]")
short-lang (keyword (str (first parts) "_" (second parts)))
shortest-lang (keyword (first parts))]
(if (and (> (count parts) 2) (contains? languages short-lang))
short-lang
(when (contains? languages shortest-lang)
shortest-lang)))))
(defn require-translation
[lang-key]
(when-let [lang (valid-language (keyword lang-key))]
(case lang
:ar (js/require "../translations/ar.json")
:bn (js/require "../translations/bn.json")
:de (js/require "../translations/de.json")
:el (js/require "../translations/el.json")
:en (js/require "../translations/en.json")
:es (js/require "../translations/es.json")
:es_419 (js/require "../translations/es_419.json")
:es_AR (js/require "../translations/es_AR.json")
:fil (js/require "../translations/fil.json")
:fr (js/require "../translations/fr.json")
:hi (js/require "../translations/hi.json")
:id (js/require "../translations/id.json")
:in (js/require "../translations/id.json")
:it (js/require "../translations/it.json")
:ja (js/require "../translations/ja.json")
:ko (js/require "../translations/ko.json")
:ms (js/require "../translations/ms.json")
:nl (js/require "../translations/nl.json")
:pl (js/require "../translations/pl.json")
:pt (js/require "../translations/pt.json")
:pt_BR (js/require "../translations/pt_BR.json")
:ru (js/require "../translations/ru.json")
:tr (js/require "../translations/tr.json")
:vi (js/require "../translations/vi.json")
:zh (js/require "../translations/zh.json")
:zh_Hant (js/require "../translations/zh_hant.json")
:zh_TW (js/require "../translations/zh_TW.json"))))
;; translations
(def translations-by-locale
(cond-> {:en (require-translation :en)}
(not= :en default-device-language)
(assoc default-device-language
(require-translation (-> (name default-device-language)
(string/replace "-" "_")
keyword)))))
(i18n/setup (name default-device-language) (clj->js translations-by-locale))
(defn load-language
[lang]
(when-let [lang-key (valid-language (keyword lang))]
(when-not (contains? @loaded-languages lang-key)
(aset (i18n/get-translations)
lang
(require-translation lang-key))
(swap! loaded-languages conj lang-key))))
(conj #{:en} i18n/default-device-language)))
+5 -6
View File
@@ -3,12 +3,11 @@
[cljs.test :refer-macros [deftest is]]
[clojure.set :as set]
[clojure.string :as string]
[i18n.i18n :as i18n]
[status-im2.setup.i18n-resources :as i18n-resources]))
[i18n.i18n :as i18n]))
;; english as source of truth
(def labels
(set (keys (js->clj (:en i18n-resources/translations-by-locale)
(set (keys (js->clj (:en i18n/translations-by-locale)
:keywordize-keys
true))))
@@ -17,7 +16,7 @@
(defn labels-for-all-locales
[]
(->> i18n-resources/translations-by-locale
(->> i18n/translations-by-locale
(mapcat #(-> % val (js->clj :keywordize-keys true) keys))
set))
@@ -1025,14 +1024,14 @@
;; locales
(def locales (set (keys i18n-resources/translations-by-locale)))
(def locales (set (keys i18n/translations-by-locale)))
(spec/def ::locale locales)
(spec/def ::locales (spec/coll-of ::locale :kind set? :into #{}))
(defn locale->labels
[locale]
(-> i18n-resources/translations-by-locale (get locale) (js->clj :keywordize-keys true) keys set))
(-> i18n/translations-by-locale (get locale) (js->clj :keywordize-keys true) keys set))
(defn locale->checkpoint
[locale]
@@ -1,7 +1,7 @@
(ns status-im2.subs.activity-center-test
(:require [cljs.test :refer [is testing]]
[re-frame.db :as rf-db]
[test-helpers.unit :as h]
[status-im.test-helpers :as h]
status-im2.subs.activity-center
[utils.re-frame :as rf]))
+6
View File
@@ -290,6 +290,12 @@
(fn [{:keys [metadata]}]
(:sending-contact-request metadata)))
(re-frame/reg-sub
:chats/sending-image
:<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}]
(:sending-image metadata)))
(re-frame/reg-sub
:chats/timeline-sending-image
:<- [:chats/timeline-chat-input]
+1 -21
View File
@@ -102,25 +102,6 @@
(fn [messages]
(empty? messages)))
(defn albumize-messages
[messages]
(get (reduce (fn [{:keys [messages albums]} message]
(let [album-id (when (:albumize? message) (:album-id message))
albums (cond-> albums album-id (update album-id conj message))
messages (if (and album-id (> (count (get albums album-id)) 3))
(conj (filterv #(not= album-id (:album-id %)) messages)
{:album (get albums album-id)
:album-id album-id
:message-id album-id
:content-type constants/content-type-album})
(conj messages message))]
{:messages messages
:albums albums}))
{:messages []
:albums {}}
messages)
:messages))
(re-frame/reg-sub
:chats/raw-chat-messages-stream
(fn [[_ chat-id] _]
@@ -145,8 +126,7 @@
(datetime/timestamp)
chat-type
joined
loading-messages?)
(albumize-messages))))))
loading-messages?))))))
;;we want to keep data unchanged so react doesn't change component when we leave screen
(def memo-profile-messages-stream (atom nil))
@@ -1,25 +0,0 @@
(ns status-im2.subs.chat.messages-test
(:require [cljs.test :refer [deftest is testing]]
[status-im2.subs.chat.messages :as messages]
[status-im2.common.constants :as constants]))
(def messages-state
[{:message-id "0x111" :album-id "abc" :albumize? true}
{:message-id "0x222" :album-id "abc" :albumize? true}
{:message-id "0x333" :album-id "abc" :albumize? true}
{:message-id "0x444" :album-id "abc" :albumize? true}
{:message-id "0x555" :album-id "efg" :albumize? true}])
(def messages-albumized-state
[{:album [{:message-id "0x444" :album-id "abc" :albumize? true}
{:message-id "0x333" :album-id "abc" :albumize? true}
{:message-id "0x222" :album-id "abc" :albumize? true}
{:message-id "0x111" :album-id "abc" :albumize? true}]
:album-id "abc"
:message-id "abc"
:content-type constants/content-type-album}
{:message-id "0x555" :album-id "efg" :albumize? true}])
(deftest albumize-messages
(testing "Finding albums in the messages list"
(is (= (messages/albumize-messages messages-state) messages-albumized-state))))
+2 -1
View File
@@ -1,7 +1,7 @@
(ns status-im2.subs.communities-test
(:require [cljs.test :refer [is testing use-fixtures]]
[re-frame.db :as rf-db]
[test-helpers.unit :as h]
[status-im.test-helpers :as h]
status-im2.subs.communities
[utils.re-frame :as rf]))
@@ -135,3 +135,4 @@
{:id "0x1" :name "Civilized monkeys"}
{:id "0x2" :name "Civilized rats"}]
(rf/sub [sub-name])))))
+2 -2
View File
@@ -1,6 +1,6 @@
(ns status-im2.subs.multiaccount
(:require [cljs.spec.alpha :as spec]
[clojure.set :as set]
[clojure.set :as clojure.set]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
@@ -23,7 +23,7 @@
(some->
current-account
(select-keys [:name :preferred-name :public-key :identicon :image :images])
(set/rename-keys {:name :alias})
(clojure.set/rename-keys {:name :alias})
(multiaccounts/contact-with-names))))
(re-frame/reg-sub
+39 -83
View File
@@ -1,67 +1,21 @@
(ns status-im2.subs.shell
(:require [re-frame.core :as re-frame]
[utils.datetime :as datetime]
[status-im2.common.constants :as constants]
[status-im.react-native.resources :as resources]))
(defn community-avatar
[community]
(let [images (:images community)]
(if (= (:id community) constants/status-community-id)
(resources/get-image :status-logo)
(when images
{:uri (:uri (or (:thumbnail images)
(:large images)
(first images)))}))))
[status-im.react-native.resources :as resources]
[status-im2.common.constants :as status-constants]))
(defn get-card-content
[chat communities]
[chat]
(let [last-message (:last-message chat)]
(merge
(when last-message
(case (:content-type last-message)
(constants/content-type-text
constants/content-type-emoji)
{:content-type constants/content-type-text
:data (get-in last-message [:content :text])}
(case (:content-type last-message)
status-constants/content-type-text
{:content-type :text
:data (get-in last-message [:content :text])}
;; Currently mock image is used as placeholder,
;; as last-message don't have image
;; https://github.com/status-im/status-mobile/issues/14625
constants/content-type-image
{:content-type constants/content-type-image
:data [{:source (resources/get-mock-image :photo2)}]}
;; Same for sticker, mock image is used
constants/content-type-sticker
{:content-type constants/content-type-sticker
:data {:source (resources/get-mock-image :sticker)}}
;; Mock Image
constants/content-type-gif
{:content-type constants/content-type-gif
:data {:source (resources/get-mock-image :gif)}}
constants/content-type-audio
{:content-type constants/content-type-audio
:data (datetime/ms-to-duration (:audio-duration-ms last-message))}
constants/content-type-community
(let [community (get communities (:community-id last-message))]
{:content-type constants/content-type-community
:data {:avatar (community-avatar community)
:community-name (:name community)}})
{:content-type constants/content-type-text
:data "Todo: Implement"}))
{:new-notifications? (pos? (:unviewed-messages-count chat))
:notification-indicator (if (pos? (:unviewed-mentions-count chat))
:counter
:unread-dot)
:counter-label (:unviewed-mentions-count chat)})))
{:content-type :text
:data "Todo: Implement"})))
(defn one-to-one-chat-card
[contact names chat id communities]
[contact names chat id]
(let [images (:images contact)
profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))]
{:title (first names)
@@ -71,20 +25,26 @@
:customization-color (or (:customization-color contact) :primary)
:on-close #(re-frame/dispatch [:shell/close-switcher-card id])
:on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 id true])
:content (get-card-content chat communities)}))
:content (get-card-content chat)}))
(defn private-group-chat-card
[chat id communities]
[chat id]
{:title (:chat-name chat)
:avatar-params {}
:customization-color (or (:customization-color chat) :primary)
:on-close #(re-frame/dispatch [:shell/close-switcher-card id])
:on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 id true])
:content (get-card-content chat communities)})
:content (get-card-content chat)})
(defn community-card
[community id]
(let [profile-picture (community-avatar community)]
[community id content]
(let [images (:images community)
profile-picture (if (= id status-constants/status-community-id)
(resources/get-image :status-logo)
(when images
{:uri (:uri (or (:thumbnail images)
(:large images)
(first images)))}))]
{:title (:name community)
:avatar-params (if profile-picture
{:source profile-picture}
@@ -93,15 +53,15 @@
:on-close #(re-frame/dispatch [:shell/close-switcher-card id])
:on-press #(re-frame/dispatch [:navigate-to-nav2 :community
{:community-id id} true])
:content {:community-info {:type :permission}}}))
:content (or content
{:content-type :community-info
:data {:type :permission}})}))
(defn community-channel-card
[community community-id channel channel-id]
[community community-id _ channel-id content]
(merge
(community-card community community-id)
{:content {:community-channel {:emoji (:emoji channel)
:channel-name (str "# " (:name channel))}}
:on-press (fn []
(community-card community community-id content)
{:on-press (fn []
(re-frame/dispatch [:navigate-to :community {:community-id community-id}])
(js/setTimeout
#(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 channel-id true])
@@ -118,32 +78,28 @@
(fn [[_ id] _]
[(re-frame/subscribe [:contacts/contact-by-identity id])
(re-frame/subscribe [:contacts/contact-two-names-by-identity id])
(re-frame/subscribe [:chats/chat id])
(re-frame/subscribe [:communities])])
(fn [[contact names chat communities] [_ id]]
(one-to-one-chat-card contact names chat id communities)))
(re-frame/subscribe [:chats/chat id])])
(fn [[contact names chat] [_ id]]
(one-to-one-chat-card contact names chat id)))
(re-frame/reg-sub
:shell/private-group-chat-card
(fn [[_ id] _]
[(re-frame/subscribe [:chats/chat id])
(re-frame/subscribe [:communities])])
(fn [[chat communities] [_ id]]
(private-group-chat-card chat id communities)))
[(re-frame/subscribe [:chats/chat id])])
(fn [[chat] [_ id]]
(private-group-chat-card chat id)))
(re-frame/reg-sub
:shell/community-card
(fn [[_ id] _]
[(re-frame/subscribe [:communities/community id])])
(fn [[community] [_ id]]
(community-card community id)))
(community-card community id nil)))
(re-frame/reg-sub
:shell/community-channel-card
(fn [[_ channel-id] _]
[(re-frame/subscribe [:chats/chat channel-id])
(re-frame/subscribe [:communities])])
(fn [[channel communities] [_ channel-id]]
(let [community-id (:community-id channel)
community (get communities (:community-id channel))]
(community-channel-card community community-id channel channel-id))))
(fn [[_ community-id channel-id _] _]
[(re-frame/subscribe [:communities/community community-id])
(re-frame/subscribe [:chats/chat channel-id])])
(fn [[community channel] [_ community-id channel-id content]]
(community-channel-card community community-id channel channel-id content)))
+1 -1
View File
@@ -1,7 +1,7 @@
(ns status-im2.subs.wallet.wallet-test
(:require [cljs.test :refer [deftest is testing]]
[re-frame.db :as rf-db]
[test-helpers.unit :as h]
[status-im.test-helpers :as h]
[status-im.utils.money :as money]
[status-im2.subs.wallet.wallet :as wallet]
[utils.re-frame :as rf]))
+3 -16
View File
@@ -1,7 +1,6 @@
(ns utils.datetime
(:require [cljs-time.coerce :as t.coerce]
[cljs-time.core :as t]
[goog.string :as gstring]
[cljs-time.format :as t.format]
[clojure.string :as string]
[i18n.i18n :as i18n]
@@ -57,7 +56,6 @@
;;;; Date formats
(defn- short-date-format [_] "dd MMM")
(defn- short-date-format-with-time [_] "dd MMM h:mm a")
(defn- datetime-within-one-week-format
[^js locsym]
@@ -87,7 +85,6 @@
(def date-fmt (get-formatter-fn medium-date-format))
(def time-fmt (get-formatter-fn short-time-format))
(def short-date-fmt (get-formatter-fn short-date-format))
(def short-date-with-time-fmt (get-formatter-fn short-date-format-with-time))
(def datetime-within-one-week-fmt (get-formatter-fn datetime-within-one-week-format))
;;;; Utilities
@@ -144,14 +141,10 @@
(defn timestamp->relative
[ms]
(let [datetime (-> ms
t.coerce/from-long
(t/plus time-zone-offset))]
(let [datetime (t.coerce/from-long ms)]
(cond
(today? datetime)
(str (string/capitalize (i18n/label :t/datetime-today))
" "
(.format ^js (time-fmt) datetime))
(.format ^js (time-fmt) datetime)
(within-last-n-days? datetime 1)
(str (string/capitalize (i18n/label :t/datetime-yesterday))
@@ -162,7 +155,7 @@
(.format ^js (datetime-within-one-week-fmt) datetime)
(current-year? datetime)
(.format ^js (short-date-with-time-fmt) datetime)
(.format ^js (short-date-fmt) datetime)
(previous-years? datetime)
(.format ^js (date-fmt) datetime))))
@@ -257,9 +250,3 @@
(defn to-ms
[sec]
(* 1000 sec))
(defn ms-to-duration
"milisecods to mm:ss format"
[ms]
(let [sec (quot ms 1000)]
(gstring/format "%02d:%02d" (quot sec 60) (mod sec 60))))
+6 -6
View File
@@ -152,9 +152,9 @@
(is (= "Jan 1, 1973" (datetime/timestamp->relative 94694400000))))
(testing "formats 7 days ago or older, but in the current year"
(is (= "03 Mar 3:15 PM" (datetime/timestamp->relative 163091745000)))
(is (= "02 Mar 3:00 PM" (datetime/timestamp->relative 163004400000)))
(is (= "01 Jan 3:00 PM" (datetime/timestamp->relative 157820400000))))
(is (= "03 Mar" (datetime/timestamp->relative 163091745000)))
(is (= "02 Mar" (datetime/timestamp->relative 163004400000)))
(is (= "01 Jan" (datetime/timestamp->relative 157820400000))))
(testing "formats dates within the last 6 days"
(is (= "Sat 3:15 PM" (datetime/timestamp->relative 163523745000)))
@@ -168,9 +168,9 @@
(is (= "Yesterday 11:59 PM" (datetime/timestamp->relative 163641599000))))
(testing "formats today, at various timestamps"
(is (= "Today 3:15 PM" (datetime/timestamp->relative 163696545000)))
(is (= "Today 12:00 PM" (datetime/timestamp->relative 163684800000)))
(is (= "Today 12:00 AM" (datetime/timestamp->relative 163641600000))))))
(is (= "3:15 PM" (datetime/timestamp->relative 163696545000)))
(is (= "12:00 PM" (datetime/timestamp->relative 163684800000)))
(is (= "12:00 AM" (datetime/timestamp->relative 163641600000))))))
#_((deftest day-relative-before-yesterday-force-24H-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.117.3",
"commit-sha1": "d40290a649133eb7b7f450b5c5b74eec28ba232d",
"src-sha256": "140j0gbp8nxzncya9mcpvlxnax5ajfl8c32ih20b29n8j525gw66"
"version": "v0.117.1a",
"commit-sha1": "b4bdfd3df6cf5fb91ab2d0e9f3b38e8d1b9703e5",
"src-sha256": "1s50q53p1j5ysnbj88c52zb2rh1ms21pnf6bjc7wja8gzcpih2wl"
}
@@ -1264,20 +1264,27 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
self.chat_1.set_reaction(message_from_sender)
message_sender = self.chat_1.chat_element_by_text(message_from_sender)
message_sender.emojis_below_message().wait_for_element_text(1)
if message_sender.emojis_below_message() != 1:
self.errors.append("Counter of reaction is not updated on your own message!")
self.device_2.just_fyi("Receiver sets own emoji and verifies counter on received message in 1-1 chat")
message_receiver = self.chat_2.chat_element_by_text(message_from_sender)
message_receiver.emojis_below_message().wait_for_element_text(1, 90)
if message_receiver.emojis_below_message() != 1:
self.errors.append("Counter of reaction is not updated on received message!")
self.chat_2.set_reaction(message_from_sender)
for counter in message_sender.emojis_below_message(), message_receiver.emojis_below_message():
if counter != 2:
self.errors.append('Counter is not updated after setting emoji from receiver!')
self.device_2.just_fyi("Receiver pick the same emoji and verify that counter will decrease for both users")
self.chat_2.set_reaction(message_from_sender)
message_sender.emojis_below_message().wait_for_element_text(1)
message_receiver.emojis_below_message().wait_for_element_text(1, 90)
for counter in message_sender.emojis_below_message(), message_receiver.emojis_below_message():
if counter != 1:
self.errors.append('Counter is not decreased after re-tapping emoji from receiver!')
self.errors.verify_no_errors()
@marks.testrail_id(702731)
@marks.xfail(reason="blocked by #14672")
def test_1_1_chat_pin_messages(self):
self.home_1.just_fyi("Check that Device1 can pin own message in 1-1 chat")
self.chat_1.send_message(self.message_1)
@@ -1312,67 +1319,64 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
self.errors.append(
"Message '%s' is missed on Pinned messages list for user %s" % (message, chat_number + 1)
)
# workaround for 14672
chat.tap_by_coordinates(500, 100)
# Part of the test is blocked by #14637
# chat.click_system_back_button()
#
# self.home_1.just_fyi("Check that Device1 can not pin more than 3 messages and 'Unpin' dialog appears")
# self.chat_1.send_message(self.message_3)
# self.chat_1.send_message(self.message_4)
# self.chat_1.pin_message(self.message_3, 'pin-to-chat')
# self.chat_1.pin_message(self.message_4, 'pin-to-chat')
# if self.chat_1.pin_limit_popover.is_element_displayed(30):
# self.chat_1.view_pinned_messages_button.click()
# self.chat_1.pinned_messages_list.message_element_by_text(
# self.message_2).click_inside_element_by_coordinate()
# self.home_1.just_fyi("Unpin one message so that another could be pinned")
# self.chat_1.element_by_translation_id('unpin-from-chat').double_click()
# self.chat_1.chat_element_by_text(self.message_4).click()
# self.chat_1.pin_message(self.message_4, 'pin-to-chat')
# if not (self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed(30) and
# self.chat_2.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed(30)):
# self.errors.append("Message 4 is not pinned in chat after unpinning previous one")
# else:
# self.errors.append("Can pin more than 3 messages in chat")
#
# self.home_1.just_fyi("Check pinned messages are visible in Pinned panel for both users")
# for chat_number, chat in enumerate([self.chat_1, self.chat_2]):
# count = chat.pinned_messages_count.text
# if count != '3':
# self.errors.append("Pinned messages count is not 3 for user %s" % (chat_number + 1))
#
# self.home_1.just_fyi("Unpin one message and check it's unpinned for another user")
# self.chat_2.chat_element_by_text(self.message_4).long_press_element()
# self.chat_2.element_by_translation_id("unpin-from-chat").click()
# self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.wait_for_invisibility_of_element()
# if self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed():
# self.errors.append("Message_4 is not unpinned!")
#
# for chat_number, chat in enumerate([self.chat_1, self.chat_2]):
# count = chat.pinned_messages_count.text
# if count != '2':
# self.errors.append(
# "Pinned messages count is not 2 after unpinning the last pinned message for user %s" % (
# chat_number + 1)
# )
chat.click_system_back_button()
self.home_1.just_fyi("Check that Device1 can not pin more than 3 messages and 'Unpin' dialog appears")
self.chat_1.send_message(self.message_3)
self.chat_1.send_message(self.message_4)
self.chat_1.pin_message(self.message_3, 'pin-to-chat')
self.chat_1.pin_message(self.message_4, 'pin-to-chat')
if self.chat_1.pin_limit_popover.is_element_displayed(30):
self.chat_1.view_pinned_messages_button.click()
self.chat_1.pinned_messages_list.message_element_by_text(
self.message_2).click_inside_element_by_coordinate()
self.home_1.just_fyi("Unpin one message so that another could be pinned")
self.chat_1.element_by_translation_id('unpin-from-chat').double_click()
self.chat_1.chat_element_by_text(self.message_4).click()
self.chat_1.pin_message(self.message_4, 'pin-to-chat')
if not (self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed(30) and
self.chat_2.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed(30)):
self.errors.append("Message 4 is not pinned in chat after unpinning previous one")
else:
self.errors.append("Can pin more than 3 messages in chat")
self.home_1.just_fyi("Check pinned messages are visible in Pinned panel for both users")
for chat_number, chat in enumerate([self.chat_1, self.chat_2]):
count = chat.pinned_messages_count.text
if count != '3':
self.errors.append("Pinned messages count is not 3 for user %s" % (chat_number + 1))
self.home_1.just_fyi("Unpin one message and check it's unpinned for another user")
self.chat_2.chat_element_by_text(self.message_4).long_press_element()
self.chat_2.element_by_translation_id("unpin-from-chat").click()
self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.wait_for_invisibility_of_element()
if self.chat_1.chat_element_by_text(self.message_4).pinned_by_label.is_element_displayed():
self.errors.append("Message_4 is not unpinned!")
for chat_number, chat in enumerate([self.chat_1, self.chat_2]):
count = chat.pinned_messages_count.text
if count != '2':
self.errors.append(
"Pinned messages count is not 2 after unpinning the last pinned message for user %s" % (
chat_number + 1)
)
# workaround for 14672
self.chat_1.tap_by_coordinates(500, 100)
self.errors.verify_no_errors()
@marks.testrail_id(702745)
@marks.xfail(reason="On profile picture failed due to #14718")
def test_1_1_chat_non_latin_messages_stack_update_profile_photo(self):
self.home_1.click_system_back_button_until_element_is_shown()
# self.home_1.click_system_back_button_until_element_is_shown()
self.home_1.browser_tab.click() # temp, until profile is on browser tab
self.profile_1.edit_profile_picture('sauce_logo.png')
self.profile_1.chats_tab.click()
self.chat_2.just_fyi("Send messages with non-latin symbols")
messages = ['hello', '¿Cómo estás tu año?', 'ё, доброго вечерочка', '® æ ç ♥']
[self.chat_2.send_message(message) for message in messages]
if not self.chat_1.chat_message_input.is_element_displayed():
self.chat_1.click_system_back_button_until_element_is_shown()
self.home_1.get_chat(self.default_username_2).click()
self.chat_1.send_message("workaround for 14637")
messages = ['hello', '¿Cómo estás tu año?', 'ё, доброго вечерочка', '® æ ç ♥']
[self.chat_2.send_message(message) for message in messages]
for message in messages:
if not self.chat_1.chat_element_by_text(message).is_element_displayed():
self.errors.append("Message with test '%s' was not received" % message)
@@ -267,7 +267,6 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
if not self.homes[0].element_by_text(message).is_element_displayed(30):
self.errors.append('%s PN was not fetched from offline' % message)
self.homes[0].click_system_back_button()
self.homes[0].chats_tab.click()
self.homes[0].get_chat(chat_name).click()
self.homes[0].just_fyi("check that messages are shown for every member")
@@ -278,7 +277,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@pytest.mark.xdist_group(name="two_2")
@pytest.mark.xdist_group(name="three_2")
@marks.new_ui_critical
class TestGroupChatMediumMultipleDeviceNewUI(MultipleSharedDeviceTestCase):
@@ -514,7 +514,7 @@ class TestPublicChatBrowserOneDeviceMerged(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@pytest.mark.xdist_group(name="one_1")
@pytest.mark.xdist_group(name="three_1")
@marks.new_ui_critical
class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
@@ -182,7 +182,7 @@ class TestActivityCenterMultipleDeviceMedium(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@pytest.mark.xdist_group(name="two_2")
@pytest.mark.xdist_group(name="four_2")
@marks.new_ui_critical
class TestActivityCenterMultipleDevicePR(MultipleSharedDeviceTestCase):
@@ -335,7 +335,7 @@ class TestDeeplinkChatProfileOneDevice(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@pytest.mark.xdist_group(name="one_1")
@pytest.mark.xdist_group(name="two_1")
@marks.new_ui_critical
class TestDeeplinkOneDeviceNewUI(MultipleSharedDeviceTestCase):

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