mirror of
https://github.com/status-im/status-react.git
synced 2025-02-20 14:48:38 +00:00
Merge branch 'develop' into 14620
This commit is contained in:
commit
9d886a18e5
@ -1,16 +1,18 @@
|
||||
{: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}
|
||||
{: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}
|
||||
: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
|
||||
|
@ -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 '[status-im.test-helpers :as h])
|
||||
(require '[test-helpers.unit :as h])
|
||||
|
||||
(re-frame/reg-sub
|
||||
:user/recipes
|
||||
|
@ -19,6 +19,11 @@ 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,8 +59,12 @@ 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;
|
||||
@ -527,45 +531,33 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void verify(final String address, final String password, final Callback callback) {
|
||||
Log.d(TAG, "verify");
|
||||
private void executeRunnableStatusGoMethod(Supplier<String> method, Callback callback) throws JSONException {
|
||||
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");
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String result = Statusgo.verifyAccountPassword(newKeystoreDir, address, password);
|
||||
|
||||
callback.invoke(result);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.verifyAccountPassword(newKeystoreDir, address, password), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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 void verifyDatabasePassword(final String keyUID, final String password, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.verifyDatabasePassword(keyUID, password), callback);
|
||||
}
|
||||
|
||||
public String getKeyStorePath(String keyUID) {
|
||||
@ -735,209 +727,59 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void addPeer(final String enode, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.addPeer(enode), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountStoreAccount(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreAccount(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountLoadAccount(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountLoadAccount(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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();
|
||||
public void multiAccountReset(final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountReset(), callback);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountDeriveAddresses(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountDeriveAddresses(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountGenerateAndDeriveAddresses(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountGenerateAndDeriveAddresses(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountStoreDerived(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountStoreDerivedAccounts(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountImportMnemonic(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportMnemonic(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void multiAccountImportPrivateKey(final String json, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.multiAccountImportPrivateKey(json), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void hashTransaction(final String txArgsJSON, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.hashTransaction(txArgsJSON), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void hashMessage(final String message, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.hashMessage(message), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -947,20 +789,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
final String keyStorePath = this.getKeyStorePath(keyUID);
|
||||
jsonConfig.put("keystorePath", keyStorePath);
|
||||
|
||||
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);
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString()), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -969,6 +798,11 @@ 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;
|
||||
@ -977,7 +811,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.inputConnectionStringForBootstrapping(connectionString,jsonConfig.toString());
|
||||
String res = Statusgo.multiformatSerializePublicKey(multiCodecKey,base58btc);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
@ -985,157 +819,117 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void hashTypedData(final String data, final Callback callback) {
|
||||
Log.d(TAG, "hashTypedData");
|
||||
public void multiformatDeserializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException {
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.hashTypedData(data);
|
||||
String res = Statusgo.multiformatDeserializePublicKey(multiCodecKey,base58btc);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void hashTypedDataV4(final String data, final Callback callback) {
|
||||
Log.d(TAG, "hashTypedDataV4");
|
||||
public void compressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException {
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.hashTypedDataV4(data);
|
||||
String res = Statusgo.compressPublicKey(multiCodecKey);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sendTransactionWithSignature(final String txArgsJSON, final String signature, final Callback callback) {
|
||||
Log.d(TAG, "sendTransactionWithSignature");
|
||||
public void decompressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException {
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.sendTransactionWithSignature(txArgsJSON, signature);
|
||||
String res = Statusgo.decompressPublicKey(multiCodecKey);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sendTransaction(final String txArgsJSON, final String password, final Callback callback) {
|
||||
Log.d(TAG, "sendTransaction");
|
||||
public void deserializeAndCompressKey(final String desktopKey, final Callback callback) throws JSONException {
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.sendTransaction(txArgsJSON, password);
|
||||
String res = Statusgo.deserializeAndCompressKey(desktopKey);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void hashTypedData(final String data, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.hashTypedData(data), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void hashTypedDataV4(final String data, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.hashTypedDataV4(data), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void sendTransactionWithSignature(final String txArgsJSON, final String signature, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.sendTransactionWithSignature(txArgsJSON, signature), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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;
|
||||
}
|
||||
public void sendTransaction(final String txArgsJSON, final String password, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.sendTransaction(txArgsJSON, password), callback);
|
||||
}
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.signTypedDataV4(data, account, password);
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
@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);
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -1240,29 +1034,13 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void callRPC(final String payload, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.callRPC(payload), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void callPrivateRPC(final String payload, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.callPrivateRPC(payload), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -1325,105 +1103,30 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void extractGroupMembershipSignatures(final String signaturePairs, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.extractGroupMembershipSignatures(signaturePairs), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void signGroupMembership(final String content, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.signGroupMembership(content), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void getNodeConfig(final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.getNodeConfig(), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void deleteMultiaccount(final String keyUID, final Callback callback) {
|
||||
Log.d(TAG, "deleteMultiaccount");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
public void deleteMultiaccount(final String keyUID, final Callback callback) throws JSONException {
|
||||
final String keyStoreDir = this.getKeyStorePath(keyUID);
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.deleteMultiaccount(keyUID, keyStoreDir);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.deleteMultiaccount(keyUID, keyStoreDir), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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;
|
||||
}
|
||||
|
||||
public void deleteImportedKey(final String keyUID, final String address, final String password, final Callback callback) throws JSONException {
|
||||
final String keyStoreDir = this.getKeyStorePath(keyUID);
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.deleteImportedKey(address, password, keyStoreDir);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.deleteImportedKey(address, password, keyStoreDir), callback);
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@ -1432,24 +1135,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void generateAliasAsync(final String seed, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.generateAlias(seed), callback);
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@ -1513,47 +1200,33 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void identiconAsync(final String seed, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.identicon(seed), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void generateAliasAndIdenticonAsync(final String seed, final Callback callback) {
|
||||
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);
|
||||
Log.d(TAG, "generateAliasAndIdenticonAsync");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, resIdenticon);
|
||||
Log.d(TAG, resAlias);
|
||||
callback.invoke(resAlias, resIdenticon);
|
||||
}
|
||||
};
|
||||
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);
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1575,24 +1248,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void validateMnemonic(final String seed, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.validateMnemonic(seed), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@ -1643,35 +1300,14 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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);
|
||||
public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) throws JSONException {
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.changeDatabasePassword(keyUID, password, newPassword), callback);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
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");
|
||||
|
||||
public void convertToKeycardAccount(final String keyUID, final String accountData, final String options, final String password, final String newPassword, final Callback callback) throws JSONException {
|
||||
final String keyStoreDir = this.getKeyStorePath(keyUID);
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String result = Statusgo.convertToKeycardAccount(keyStoreDir, accountData, options, password, newPassword);
|
||||
callback.invoke(result);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
executeRunnableStatusGoMethod(() -> Statusgo.convertToKeycardAccount(keyStoreDir, accountData, options, password, newPassword), callback);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -339,6 +339,38 @@ 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: 878 B After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
resources/images/mock/coinbase@2x.png
Normal file
BIN
resources/images/mock/coinbase@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
@ -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-im.chat.models-test$"
|
||||
;;:ns-regexp "status-im2.subs.subs-test$"
|
||||
:main
|
||||
status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
|
@ -1,78 +1,14 @@
|
||||
(ns i18n.i18n
|
||||
(:require ["i18n-js" :as i18n]
|
||||
[clojure.string :as string]
|
||||
[status-im.goog.i18n :as goog.i18n]
|
||||
[react-native.languages :as react-native-languages]))
|
||||
[status-im.goog.i18n :as goog.i18n]))
|
||||
|
||||
(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
|
||||
[]
|
||||
(defn setup
|
||||
[default-device-language translations-by-locale]
|
||||
(set! (.-fallbacks i18n) true)
|
||||
(set! (.-defaultSeparator i18n) "/")
|
||||
(set! (.-locale i18n) (name default-device-language))
|
||||
(set! (.-translations i18n) (clj->js translations-by-locale)))
|
||||
(set! (.-locale i18n) default-device-language)
|
||||
(set! (.-translations i18n) translations-by-locale))
|
||||
|
||||
(defn get-translations
|
||||
[]
|
||||
@ -134,12 +70,3 @@
|
||||
(.-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))))
|
||||
|
@ -141,7 +141,7 @@
|
||||
(if profile-picture
|
||||
;; display image
|
||||
[fast-image/fast-image
|
||||
{:source {:uri profile-picture}
|
||||
{:source profile-picture
|
||||
:style (container-styling inner-dimensions outer-dimensions)}]
|
||||
;; else display initials
|
||||
[container inner-dimensions outer-dimensions
|
||||
|
@ -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-20
|
||||
:border-color {:default colors/neutral-30
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-20}}
|
||||
:disabled colors/neutral-30}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
@ -138,7 +138,8 @@
|
||||
|
||||
(defn shape-style-container
|
||||
[type icon size]
|
||||
{:border-radius (if (and icon (#{:primary :secondary :danger} type))
|
||||
{:height size
|
||||
:border-radius (if (and icon (#{:primary :secondary :danger} type))
|
||||
24
|
||||
(case size
|
||||
56 12
|
||||
|
@ -81,19 +81,21 @@
|
||||
context))))
|
||||
|
||||
(defn- activity-message
|
||||
[{:keys [title body]}]
|
||||
[{:keys [title body title-number-of-lines body-number-of-lines]}]
|
||||
[rn/view {:style style/message-container}
|
||||
(when title
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:accessibility-label :activity-message-title
|
||||
:style style/message-title}
|
||||
:style style/message-title
|
||||
:number-of-lines title-number-of-lines}
|
||||
title])
|
||||
(if (string? body)
|
||||
[text/text
|
||||
{:style style/message-body
|
||||
:accessibility-label :activity-message-body
|
||||
:size :paragraph-1}
|
||||
:size :paragraph-1
|
||||
:number-of-lines body-number-of-lines}
|
||||
body]
|
||||
body)])
|
||||
|
||||
|
40
src/quo2/components/profile/profile_card/style.cljs
Normal file
40
src/quo2/components/profile/profile_card/style.cljs
Normal file
@ -0,0 +1,40 @@
|
||||
(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})
|
64
src/quo2/components/profile/profile_card/view.cljs
Normal file
64
src/quo2/components/profile/profile_card/view.cljs
Normal file
@ -0,0 +1,64 @@
|
||||
(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])])
|
@ -6,12 +6,6 @@
|
||||
[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))))
|
||||
@ -30,7 +24,7 @@
|
||||
:padding-left 8
|
||||
:background-color (if (= theme :light)
|
||||
colors/neutral-10
|
||||
colors/neutral-80)}
|
||||
colors/neutral-90)}
|
||||
style)]
|
||||
children))))
|
||||
|
||||
@ -40,7 +34,8 @@
|
||||
[base-tag
|
||||
(-> opts
|
||||
(select-keys [:override-theme :style])
|
||||
(assoc-in [:style :padding-left] 3))
|
||||
(assoc-in [:style :padding-left] 3)
|
||||
(assoc-in [:style :padding-vertical] 2))
|
||||
[group-avatar/group-avatar opts]
|
||||
[text/text
|
||||
{:weight :medium
|
||||
@ -69,7 +64,7 @@
|
||||
[rn/image
|
||||
{:style {:width 20
|
||||
:border-radius 10
|
||||
:background-color :white
|
||||
:background-color :red
|
||||
:height 20}
|
||||
:source photo}]
|
||||
[rn/view
|
||||
@ -88,3 +83,44 @@
|
||||
[]
|
||||
(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])
|
||||
|
@ -52,6 +52,7 @@
|
||||
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)
|
||||
@ -74,6 +75,8 @@
|
||||
(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)
|
||||
@ -127,6 +130,9 @@
|
||||
(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)
|
||||
|
@ -184,9 +184,11 @@
|
||||
|
||||
(defn build-image-messages
|
||||
[{db :db} chat-id]
|
||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])]
|
||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
|
||||
album-id (str (random-uuid))]
|
||||
(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,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]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn cursor->clock-value
|
||||
[^js cursor]
|
||||
@ -101,6 +101,17 @@
|
||||
: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]}
|
||||
@ -131,8 +142,8 @@
|
||||
current-clock-value (get-in db
|
||||
[:pagination-info chat-id
|
||||
:cursor-clock-value])
|
||||
clock-value (when cursor
|
||||
(cursor->clock-value cursor))]
|
||||
clock-value (when cursor (cursor->clock-value cursor))
|
||||
new-messages (map mark-album new-messages)]
|
||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||
:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
|
@ -20,7 +20,8 @@
|
||||
from
|
||||
outgoing
|
||||
whisper-timestamp
|
||||
deleted-for-me?]}]
|
||||
deleted-for-me?
|
||||
albumize?]}]
|
||||
(-> {:whisper-timestamp whisper-timestamp
|
||||
:from from
|
||||
:one-to-one? (= constants/message-type-one-to-one message-type)
|
||||
@ -32,7 +33,8 @@
|
||||
:clock-value clock-value
|
||||
:type :message
|
||||
:message-id message-id
|
||||
:outgoing (boolean outgoing)}
|
||||
:outgoing (boolean outgoing)
|
||||
:albumize? albumize?}
|
||||
add-datemark
|
||||
add-timestamp))
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.communities.core
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as 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]
|
||||
(clojure.set/rename-keys r
|
||||
{:communityId :community-id
|
||||
:publicKey :public-key
|
||||
:chatId :chat-id}))
|
||||
(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
|
||||
(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?})
|
||||
(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)))
|
||||
|
@ -205,9 +205,26 @@
|
||||
(def ^:const community-member-role-manage-users 2)
|
||||
(def ^:const community-member-role-moderator 3)
|
||||
|
||||
(def local-pairing-connection-string-identifier
|
||||
(def ^:const 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")
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.contact.db
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as 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])
|
||||
(clojure.set/rename-keys {:name :alias
|
||||
:preferred-name :name}))
|
||||
(set/rename-keys {:name :alias
|
||||
:preferred-name :name}))
|
||||
all-contacts (cond-> contacts
|
||||
current-contact
|
||||
(assoc public-key current-contact))]
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.data-store.chats
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as 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
|
||||
(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})
|
||||
(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 %)))
|
||||
|
@ -1,12 +1,12 @@
|
||||
(ns status-im.data-store.contacts
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as set]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn <-rpc
|
||||
[contact]
|
||||
(-> contact
|
||||
(clojure.set/rename-keys
|
||||
(set/rename-keys
|
||||
{:id :public-key
|
||||
:ensVerifiedAt :ens-verified-at
|
||||
:displayName :display-name
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.data-store.messages
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as set]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@ -10,39 +10,40 @@
|
||||
(assoc :text (:text content)
|
||||
:sticker (:sticker content))
|
||||
:always
|
||||
(clojure.set/rename-keys {:chat-id :chat_id
|
||||
:whisper-timestamp :whisperTimestamp
|
||||
:community-id :communityId
|
||||
:clock-value :clock})))
|
||||
(set/rename-keys {:chat-id :chat_id
|
||||
:whisper-timestamp :whisperTimestamp
|
||||
:community-id :communityId
|
||||
:clock-value :clock})))
|
||||
|
||||
(defn <-rpc
|
||||
[message]
|
||||
(-> message
|
||||
(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?})
|
||||
(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?})
|
||||
|
||||
(update :quoted-message
|
||||
clojure.set/rename-keys
|
||||
set/rename-keys
|
||||
{:parsedText :parsed-text :communityId :community-id})
|
||||
(update :outgoing-status keyword)
|
||||
(update :command-parameters
|
||||
clojure.set/rename-keys
|
||||
set/rename-keys
|
||||
{:transactionHash :transaction-hash
|
||||
:commandState :command-state})
|
||||
(assoc :content {:chat-id (:chatId message)
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.data-store.pin-messages
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as 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)))
|
||||
(clojure.set/rename-keys {:pinnedAt :pinned-at
|
||||
:pinnedBy :pinned-by})
|
||||
(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 (clojure.set/rename-keys result
|
||||
{:pinnedMessages
|
||||
:pinned-messages})]
|
||||
(let [result (set/rename-keys result
|
||||
{:pinnedMessages
|
||||
:pinned-messages})]
|
||||
(on-success (update result :pinned-messages #(map <-rpc %)))))
|
||||
:on-error on-error}]})
|
||||
|
||||
|
@ -1,24 +1,24 @@
|
||||
(ns status-im.data-store.reactions
|
||||
(:require [clojure.set :as clojure.set]))
|
||||
(:require [clojure.set :as set]))
|
||||
|
||||
(defn ->rpc
|
||||
[message]
|
||||
(-> message
|
||||
(clojure.set/rename-keys {:message-id :messageId
|
||||
:emoji-id :emojiId
|
||||
:chat-id :localChatId
|
||||
:message-type :messageType
|
||||
:emoji-reaction-id :id})))
|
||||
(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)
|
||||
(clojure.set/rename-keys {:messageId :message-id
|
||||
:localChatId :chat-id
|
||||
:emojiId :emoji-id
|
||||
:messageType :message-type
|
||||
:id :emoji-reaction-id})))
|
||||
(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
|
||||
|
41
src/status_im/data_store/switcher_cards.cljs
Normal file
41
src/status_im/data_store/switcher_cards.cljs
Normal file
@ -0,0 +1,41 @@
|
||||
(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 clojure.set]
|
||||
(:require [clojure.set :as set]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn <-rpc
|
||||
[visibility-status-update]
|
||||
(clojure.set/rename-keys visibility-status-update
|
||||
{:publicKey :public-key
|
||||
:statusType :status-type}))
|
||||
(set/rename-keys visibility-status-update
|
||||
{:publicKey :public-key
|
||||
:statusType :status-type}))
|
||||
(defn <-rpc-settings
|
||||
[settings]
|
||||
(-> settings
|
||||
(clojure.set/rename-keys
|
||||
(set/rename-keys
|
||||
{:current-user-status :current-user-visibility-status})
|
||||
(update :current-user-visibility-status <-rpc)))
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
[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]
|
||||
@ -473,7 +474,8 @@
|
||||
(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))))
|
||||
(visibility-status-updates-store/fetch-visibility-status-updates-rpc)
|
||||
(switcher-cards-store/fetch-switcher-cards-rpc))))
|
||||
|
||||
(defn get-new-auth-method
|
||||
[auth-method save-password?]
|
||||
|
@ -5,7 +5,8 @@
|
||||
[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]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(defn status
|
||||
[]
|
||||
@ -278,6 +279,55 @@
|
||||
: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,7 +2,7 @@
|
||||
(:require ["react-native" :as rn]
|
||||
["react-native-gesture-handler" :refer (gestureHandlerRootHOC)]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
[clojure.set :as clojure.set]
|
||||
[clojure.set :as 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 (clojure.set/map-invert tab-key-idx) selected-tab-index)]
|
||||
tab-key (get (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)
|
||||
|
@ -63,7 +63,8 @@
|
||||
: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")})
|
||||
:user-picture-male5 (js/require "../resources/images/mock/user_picture_male5.png")
|
||||
:coinbase (js/require "../resources/images/mock/coinbase.png")})
|
||||
|
||||
(defn get-theme-image
|
||||
[k]
|
||||
|
@ -199,6 +199,12 @@
|
||||
{: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)]
|
||||
@ -229,7 +235,8 @@
|
||||
(cb {:type handler :community-id (:community-id route-params)})
|
||||
|
||||
(= handler :community)
|
||||
(cb {:type handler :community-id (:community-id route-params)})
|
||||
(cb {:type (community-route-type route-params)
|
||||
:community-id (:community-id route-params)})
|
||||
|
||||
(= handler :community-chat)
|
||||
(cb {:type handler :chat-id (:chat-id route-params)})
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.signing.core
|
||||
(:require [clojure.set :as clojure.set]
|
||||
(:require [clojure.set :as 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])
|
||||
(clojure.set/rename-keys {:input :data}))})))
|
||||
(set/rename-keys {:input :data}))})))
|
||||
|
@ -5,9 +5,7 @@
|
||||
[shadow.test :as st]
|
||||
[shadow.test.env :as env]
|
||||
[utils.re-frame :as rf]
|
||||
[i18n.i18n :as i18n]))
|
||||
|
||||
(i18n/init)
|
||||
status-im2.setup.i18n-resources))
|
||||
|
||||
(defonce repl? (atom false))
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
(defn build-message
|
||||
[{:keys [chat-id
|
||||
album-id
|
||||
text
|
||||
response-to
|
||||
ens-name
|
||||
@ -15,6 +16,7 @@
|
||||
sticker
|
||||
content-type]}]
|
||||
{:chatId chat-id
|
||||
:albumId album-id
|
||||
:text text
|
||||
:responseTo response-to
|
||||
:ensName ens-name
|
||||
|
@ -4,10 +4,11 @@
|
||||
[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-im.ui.components.react :as react]
|
||||
[status-im2.setup.i18n-resources :as i18n-resources]
|
||||
[i18n.i18n :as i18n])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn- start-chat
|
||||
@ -73,8 +74,8 @@
|
||||
|
||||
(defn get-language-topic
|
||||
[]
|
||||
(let [lang (subs (name i18n/default-device-language) 0 2)
|
||||
lang3 (subs (name i18n/default-device-language) 0 3)
|
||||
(let [lang (subs (name i18n-resources/default-device-language) 0 2)
|
||||
lang3 (subs (name i18n-resources/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 clojure.set]
|
||||
(:require [clojure.set :as 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 (clojure.set/rename-keys home-item {:id :chat-id})]
|
||||
home-item (set/rename-keys home-item {:id :chat-id})]
|
||||
[rn/view
|
||||
{:accessibility-label :chat-item
|
||||
:style (merge styles/category-item
|
||||
|
@ -108,7 +108,6 @@
|
||||
[status-im.ui.screens.wallet.swap.views :as wallet.swap]
|
||||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||
[status-im2.contexts.chat.group-details.view :as group-details]
|
||||
[status-im.ui2.screens.chat.photo-selector.view :as photo-selector]
|
||||
[status-im.ui2.screens.chat.components.new-chat.view :as new-chat-aio]))
|
||||
|
||||
(defn right-button-options
|
||||
@ -207,10 +206,6 @@
|
||||
:options {:topBar {:visible false}}
|
||||
:component pin-messages/pinned-messages}
|
||||
|
||||
{:name :photo-selector
|
||||
:options {:topBar {:visible false}}
|
||||
:component photo-selector/photo-selector}
|
||||
|
||||
{:name :group-chat-profile
|
||||
;;TODO animated-header
|
||||
:options {:topBar {:visible false}}
|
||||
|
@ -64,14 +64,9 @@
|
||||
(i18n/label :t/message-deleted)]])
|
||||
|
||||
(defn reply-message
|
||||
[{:keys [chat-id id]}
|
||||
[{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?]}
|
||||
in-chat-input? pin?]
|
||||
(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])
|
||||
(let [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
|
||||
|
@ -15,7 +15,7 @@
|
||||
[status-im.ui2.screens.chat.composer.mentions :as mentions]
|
||||
[status-im.ui2.screens.chat.composer.reply :as reply]
|
||||
[status-im.ui2.screens.chat.composer.style :as style]
|
||||
[status-im.ui2.screens.chat.photo-selector.view :as photo-selector]
|
||||
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.contexts.chat.messages.list.view :refer [scroll-to-bottom]]
|
||||
@ -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] ;; TODO move to status-im2
|
||||
[status-im.ui2.screens.chat.pin-limit-popover.style :as style]
|
||||
[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 8}]]]))])
|
||||
:size 12}]]]))])
|
||||
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.wallet.choose-recipient.core :as choose-recipient]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.native-module.core :as status]))
|
||||
|
||||
;; TODO(yenda) investigate why `handle-universal-link` event is
|
||||
;; dispatched 7 times for the same link
|
||||
@ -76,7 +77,21 @@
|
||||
(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}))
|
||||
(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)]))))
|
||||
|
||||
(rf/defn handle-community-chat
|
||||
[cofx {:keys [chat-id]}]
|
||||
@ -145,6 +160,7 @@
|
||||
: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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.utils.views
|
||||
(:require [clojure.walk :as w]))
|
||||
(:require [clojure.walk :as walk]))
|
||||
|
||||
(defn atom?
|
||||
[sub]
|
||||
@ -9,9 +9,9 @@
|
||||
(defn walk-sub
|
||||
[sub form->sym]
|
||||
(if (coll? sub)
|
||||
(w/postwalk (fn [f]
|
||||
(or (form->sym f) f))
|
||||
sub)
|
||||
(walk/postwalk (fn [f]
|
||||
(or (form->sym f) f))
|
||||
sub)
|
||||
(or (form->sym sub) sub)))
|
||||
|
||||
(defn prepare-subs
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns status-im.wallet.core
|
||||
(:require
|
||||
[clojure.set :as clojure.set]
|
||||
[clojure.set :as 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 clojure.set/union chain-visible-tokens)
|
||||
(update visible-tokens chain 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]}]
|
||||
[{:keys [title description context button-text on-press extra-action extra-text accessibility-label]}]
|
||||
(let [extra-action-selected? (reagent/atom false)]
|
||||
(fn []
|
||||
(let [{:keys [group-chat chat-id public-key color name]} context
|
||||
@ -38,7 +38,9 @@
|
||||
id]))
|
||||
photo-path (when-not (empty? (:images contact))
|
||||
(rf/sub [:chats/photo-path id]))]
|
||||
[rn/view {:style {:margin-horizontal 20}}
|
||||
[rn/view
|
||||
{:style {:margin-horizontal 20}
|
||||
:accessibility-label accessibility-label}
|
||||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:size :heading-1} title]
|
||||
|
@ -13,6 +13,9 @@
|
||||
(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)
|
||||
@ -198,3 +201,20 @@
|
||||
|
||||
(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}})
|
||||
|
@ -8,19 +8,20 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- entry
|
||||
[{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
|
||||
[{:keys [icon label on-press danger? sub-label chevron? add-divider? accessibility-label]}]
|
||||
{: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?})
|
||||
{: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})
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
@ -54,11 +55,12 @@
|
||||
[: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
|
||||
: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
|
||||
:accessibility-label :clear-history-confirm
|
||||
: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}]
|
||||
@ -66,11 +68,12 @@
|
||||
[: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
|
||||
: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
|
||||
:accessibility-label :delete-chat-confirm
|
||||
: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]
|
||||
@ -78,14 +81,15 @@
|
||||
[: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
|
||||
: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
|
||||
: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]))}))}]))
|
||||
|
||||
(defn block-user-action
|
||||
[{:keys [public-key] :as item}]
|
||||
@ -93,255 +97,281 @@
|
||||
[: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
|
||||
: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
|
||||
:accessibility-label :block-user
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :mute-chat
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :mark-as-read
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :clear-history
|
||||
: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
|
||||
:sub-label nil
|
||||
:chevron? false}))
|
||||
(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}))
|
||||
|
||||
(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
|
||||
: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
|
||||
:accessibility-label :leave-group
|
||||
: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
|
||||
:sub-label nil
|
||||
:chevron? false}))
|
||||
(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}))
|
||||
|
||||
(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
|
||||
:sub-label nil
|
||||
:chevron? false}))
|
||||
(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}))
|
||||
|
||||
;; 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
|
||||
: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
|
||||
:accessibility-label :edit-name-and-image
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :manage-notifications
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :fetch-messages
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :pinned-messages
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :remove-from-contacts
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :rename-contact
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :show-qr-code
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :share-profile
|
||||
: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
|
||||
:sub-label nil
|
||||
:chevron? false}))
|
||||
(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}))
|
||||
|
||||
;; 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
|
||||
: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
|
||||
:accessibility-label :mark-untrustworthy
|
||||
: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
|
||||
:sub-label nil
|
||||
:chevron? false}))
|
||||
(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}))
|
||||
|
||||
(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
|
||||
: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
|
||||
:accessibility-label :remove-from-group
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :group-details
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :add-members
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :manage-members
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :edit-group
|
||||
: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
|
||||
: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
|
||||
:accessibility-label :group-privacy
|
||||
: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
|
||||
[status-im.test-helpers :as h]
|
||||
[test-helpers.unit :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-without-feedback
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn []
|
||||
(rf/dispatch [:hide-popover])
|
||||
(rf/dispatch [:contact.ui/send-message-pressed
|
||||
|
@ -9,12 +9,19 @@
|
||||
[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 2
|
||||
{:number-of-lines 1
|
||||
:style style/tag-text
|
||||
:accessibility-label :activity-message-body
|
||||
:size :paragraph-1}]
|
||||
@ -29,25 +36,25 @@
|
||||
parsed-text-children))))
|
||||
|
||||
(defn view
|
||||
[{: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)}}]])
|
||||
[{: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)}}]]))
|
||||
|
@ -0,0 +1,12 @@
|
||||
(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})
|
@ -0,0 +1,53 @@
|
||||
(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)}}]]))
|
@ -9,6 +9,7 @@
|
||||
[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]))
|
||||
|
||||
@ -107,6 +108,9 @@
|
||||
types/mention
|
||||
[mentions/view notification]
|
||||
|
||||
types/reply
|
||||
[reply/view notification]
|
||||
|
||||
nil)])
|
||||
|
||||
(defn view
|
||||
|
@ -0,0 +1,22 @@
|
||||
(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})
|
@ -0,0 +1,51 @@
|
||||
(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,6 +10,7 @@
|
||||
[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]
|
||||
@ -94,6 +95,8 @@
|
||||
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,7 +179,9 @@
|
||||
:on-layout on-messages-view-layout})]
|
||||
[quo/floating-shell-button
|
||||
(merge {:jump-to
|
||||
{:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
|
||||
{:on-press #(do
|
||||
(rf/dispatch [:close-chat])
|
||||
(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}}))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.ui2.screens.chat.photo-selector.style
|
||||
(ns status-im2.contexts.chat.photo-selector.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
@ -37,6 +37,11 @@
|
||||
:margin-left 20
|
||||
:margin-bottom 24})
|
||||
|
||||
(def title-container
|
||||
{:flex-direction :row
|
||||
:position :absolute
|
||||
:align-self :center})
|
||||
|
||||
(defn chevron-container
|
||||
[]
|
||||
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
|
||||
@ -68,3 +73,4 @@
|
||||
:border-radius 8
|
||||
:top 8
|
||||
:right 8})
|
||||
|
@ -1,69 +1,82 @@
|
||||
(ns status-im.ui2.screens.chat.photo-selector.view
|
||||
(ns status-im2.contexts.chat.photo-selector.view
|
||||
(:require [i18n.i18n :as i18n]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo2.components.notifications.info-count :as info-count]
|
||||
[quo2.core :as quo2]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui2.screens.chat.photo-selector.style :as style]
|
||||
[status-im2.contexts.chat.photo-selector.style :as style]
|
||||
[status-im.utils.core :as utils]
|
||||
[quo.react]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def selected (reagent/atom []))
|
||||
|
||||
(defn on-press-confirm-selection
|
||||
[chat-id]
|
||||
(rf/dispatch [:chat.ui/clear-sending-images chat-id])
|
||||
(doseq [item @selected]
|
||||
(rf/dispatch [:chat.ui/camera-roll-pick item]))
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))
|
||||
|
||||
(defn bottom-gradient
|
||||
[chat-id selected-images]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [safe-area (safe-area/use-safe-area)]
|
||||
(when (or (pos? (count @selected)) selected-images)
|
||||
(when (or (seq @selected) selected-images)
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container safe-area)}
|
||||
[quo2/button
|
||||
{:style {:align-self :stretch
|
||||
:margin-horizontal 20}
|
||||
:on-press #(do
|
||||
(rf/dispatch [:chat.ui/clear-sending-images chat-id])
|
||||
(doseq [item @selected]
|
||||
(rf/dispatch [:chat.ui/camera-roll-pick item]))
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))}
|
||||
[quo/button
|
||||
{:style {:align-self :stretch
|
||||
:margin-horizontal 20}
|
||||
:on-press #(on-press-confirm-selection chat-id)
|
||||
:accessibility-label :confirm-selection}
|
||||
(i18n/label :t/confirm-selection)]])))])
|
||||
|
||||
(defn clear-button
|
||||
[]
|
||||
(when (pos? (count @selected))
|
||||
(when (seq @selected)
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(reset! selected [])
|
||||
:style (style/clear-container)}
|
||||
[quo2/text {:weight :medium} (i18n/label :t/clear)]]))
|
||||
{:on-press #(reset! selected [])
|
||||
:style (style/clear-container)
|
||||
:accessibility-label :clear}
|
||||
[quo/text {:weight :medium} (i18n/label :t/clear)]]))
|
||||
|
||||
(defn remove-selected
|
||||
[coll item]
|
||||
(vec (remove #(= % item) coll)))
|
||||
|
||||
(defn image
|
||||
[item index _ {:keys [window-width]}]
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(if (some #{item} @selected)
|
||||
(reset! selected (vec (remove #(= % item) @selected)))
|
||||
(swap! selected conj item)))}
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(if (some #{item} @selected)
|
||||
(swap! selected remove-selected item)
|
||||
(swap! selected conj item)))
|
||||
:accessibility-label (str "image-" index)}
|
||||
[rn/image
|
||||
{:source {:uri item}
|
||||
:style (style/image window-width index)}]
|
||||
(when (some #{item} @selected)
|
||||
[rn/view {:style (style/overlay window-width)}])
|
||||
(when (some #{item} @selected)
|
||||
[info-count/info-count {:style style/image-count}
|
||||
[info-count/info-count
|
||||
{:style style/image-count
|
||||
:accessibility-label (str "count-" index)}
|
||||
(inc (utils/first-index #(= item %) @selected))])])
|
||||
|
||||
(defn photo-selector
|
||||
[chat-id]
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20])
|
||||
(let [selected-images (keys (get-in (rf/sub [:chat/inputs]) [chat-id :metadata :sending-image]))]
|
||||
(let [selected-images (keys (rf/sub [:chats/sending-image]))]
|
||||
(when selected-images
|
||||
(reset! selected (vec selected-images)))
|
||||
[:f>
|
||||
@ -78,17 +91,15 @@
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(js/alert "Camera: not implemented")
|
||||
:style (style/camera-button-container)}
|
||||
[quo2/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
||||
[quo/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:position :absolute
|
||||
:align-self :center}}
|
||||
[quo2/text {:weight :medium} (i18n/label :t/recent)]
|
||||
{:style style/title-container}
|
||||
[quo/text {:weight :medium} (i18n/label :t/recent)]
|
||||
[rn/view {:style (style/chevron-container)}
|
||||
[quo2/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
|
||||
[quo/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
|
||||
[clear-button]
|
||||
[rn/flat-list
|
||||
{:key-fn (fn [item] item)
|
||||
{:key-fn identity
|
||||
:render-fn image
|
||||
:render-data {:window-width window-width}
|
||||
:data camera-roll-photos
|
||||
@ -100,3 +111,4 @@
|
||||
has-next-page?])}]
|
||||
[bottom-gradient chat-id selected-images]]))]))
|
||||
|
||||
|
@ -45,11 +45,13 @@
|
||||
[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]
|
||||
@ -63,7 +65,6 @@
|
||||
[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
|
||||
@ -175,6 +176,9 @@
|
||||
: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,6 +108,7 @@
|
||||
: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*)))
|
||||
|
@ -0,0 +1,94 @@
|
||||
(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,6 +2,7 @@
|
||||
(: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]
|
||||
@ -19,6 +20,8 @@
|
||||
: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
|
||||
@ -51,26 +54,20 @@
|
||||
{:label "Content Type"
|
||||
:key :content-type
|
||||
:type :select
|
||||
:options [{:key :text
|
||||
:options [{:key constants/content-type-text
|
||||
:value :text}
|
||||
{:key :photo
|
||||
{:key constants/content-type-image
|
||||
:value :photo}
|
||||
{:key :sticker
|
||||
{:key constants/content-type-sticker
|
||||
:value :sticker}
|
||||
{:key :gif
|
||||
{:key constants/content-type-gif
|
||||
:value :gif}
|
||||
{:key :audio
|
||||
{:key constants/content-type-audio
|
||||
:value :audio}
|
||||
{:key :community
|
||||
{:key constants/content-type-community
|
||||
:value :community}
|
||||
{:key :link
|
||||
:value :link}
|
||||
{:key :code
|
||||
:value :code}
|
||||
{:key :channel
|
||||
:value :channel}
|
||||
{:key :community-info
|
||||
:value :community-info}]}
|
||||
{:key constants/content-type-link
|
||||
:value :link}]}
|
||||
{:label "Last Message"
|
||||
:key :last-message
|
||||
:type :text}
|
||||
@ -90,6 +87,7 @@
|
||||
(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)}
|
||||
@ -102,13 +100,27 @@
|
||||
(defn get-mock-content
|
||||
[data]
|
||||
(case (:content-type data)
|
||||
: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))
|
||||
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))
|
||||
|
||||
(defn get-mock-data
|
||||
[{:keys [type] :as data}]
|
||||
@ -120,11 +132,19 @@
|
||||
: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 {: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
|
||||
shell.constants/community-channel-card)
|
||||
{:avatar-params community-avatar}
|
||||
{})))
|
||||
|
||||
(defn cool-preview
|
||||
@ -136,7 +156,7 @@
|
||||
:banner? false
|
||||
:notification-indicator :counter
|
||||
:counter-label 2
|
||||
:content-type :text
|
||||
:content-type constants/content-type-text
|
||||
:last-message "This is fantastic! Ethereum"
|
||||
:preview-label-color colors/white})]
|
||||
(fn []
|
||||
@ -151,7 +171,7 @@
|
||||
(defn preview-switcher-cards
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color colors/neutral-100
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-90)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
|
@ -3,6 +3,7 @@
|
||||
[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]))
|
||||
|
||||
@ -19,6 +20,8 @@
|
||||
(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
|
||||
@ -30,7 +33,11 @@
|
||||
{:key :group-avatar
|
||||
:value "Group avatar"}
|
||||
{:key :context-tag
|
||||
:value "Context tag"}]}])
|
||||
:value "Context tag"}
|
||||
{:key :audio
|
||||
:value "Audio"}
|
||||
{:key :community
|
||||
:value "Community"}]}])
|
||||
|
||||
(def context-tag-descriptor
|
||||
[{:label "Label"
|
||||
@ -100,13 +107,17 @@
|
||||
:public-key
|
||||
[quo2/public-key-tag {} example-pk]
|
||||
:avatar
|
||||
[quo2/user-avatar-tag {} current-username (:photo @state)])]]]))))
|
||||
[quo2/user-avatar-tag {} current-username (:photo @state)]
|
||||
:audio
|
||||
[quo2/audio-tag "00:32"]
|
||||
:community
|
||||
[quo2/community-tag coinbase-community "Coinbase"])]]]))))
|
||||
|
||||
(defn preview-context-tags
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (colors/theme-colors colors/white
|
||||
colors/neutral-90)
|
||||
colors/neutral-95)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
|
@ -5,59 +5,85 @@
|
||||
[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
|
||||
[{:keys [content-type data new-notifications? color-50]}]
|
||||
[type {:keys [content-type data new-notifications? color-50 community-info community-channel]}]
|
||||
[rn/view {:style (style/content-container new-notifications?)}
|
||||
;; 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
|
||||
[:<>])])
|
||||
(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))])
|
||||
|
||||
(defn notification-container
|
||||
[{:keys [notification-indicator counter-label color-60]}]
|
||||
@ -70,9 +96,9 @@
|
||||
[rn/view {:style (style/unread-dot color-60)}])])
|
||||
|
||||
(defn bottom-container
|
||||
[{:keys [new-notifications?] :as content}]
|
||||
[type {:keys [new-notifications?] :as content}]
|
||||
[:<>
|
||||
[content-container content]
|
||||
[content-container type content]
|
||||
(when new-notifications?
|
||||
[notification-container content])])
|
||||
|
||||
@ -92,7 +118,8 @@
|
||||
:size :large
|
||||
:override-theme :dark}]
|
||||
|
||||
shell.constants/community-card
|
||||
(shell.constants/community-card
|
||||
shell.constants/community-channel-card)
|
||||
(if (:source avatar-params)
|
||||
[fast-image/fast-image
|
||||
{:source (:source avatar-params)
|
||||
@ -106,19 +133,41 @@
|
||||
(string/upper-case (first (:name avatar-params)))]])))
|
||||
|
||||
(defn subtitle
|
||||
[{: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)))
|
||||
[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)
|
||||
|
||||
"")))
|
||||
|
||||
;; Screens Card
|
||||
(defn screens-card
|
||||
@ -144,8 +193,8 @@
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/subtitle}
|
||||
(subtitle content)]
|
||||
[bottom-container (merge {:color-50 color-50 :color-60 color-60} content)]]
|
||||
(subtitle type content)]
|
||||
[bottom-container type (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]])
|
||||
@ -188,30 +237,26 @@
|
||||
(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/one-to-one-chat-card ;; Screens Card
|
||||
shell.constants/private-group-chat-card
|
||||
shell.constants/community-card
|
||||
shell.constants/community-channel-card)
|
||||
[screens-card data]
|
||||
|
||||
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
|
||||
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]))
|
||||
|
@ -60,8 +60,9 @@
|
||||
(def ^:const one-to-one-chat-card 1)
|
||||
(def ^:const private-group-chat-card 2)
|
||||
(def ^:const community-card 3)
|
||||
(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)
|
||||
(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)
|
||||
|
@ -1,10 +1,12 @@
|
||||
(ns status-im2.contexts.shell.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require [utils.re-frame :as rf]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.core :as utils]
|
||||
[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-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
[status-im.data-store.switcher-cards :as switcher-cards-store]))
|
||||
|
||||
;; Effects
|
||||
|
||||
@ -29,62 +31,76 @@
|
||||
|
||||
;; Events
|
||||
|
||||
(rf/defn add-switcher-card
|
||||
{:events [:shell/add-switcher-card]}
|
||||
[{:keys [db now] :as cofx} view-id id]
|
||||
(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]
|
||||
(case view-id
|
||||
:chat
|
||||
(let [chat (get-in db [:chats id])]
|
||||
(case (:chat-type chat)
|
||||
constants/one-to-one-chat-type
|
||||
{: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})}
|
||||
{: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}}
|
||||
|
||||
constants/private-group-chat-type
|
||||
{: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})}
|
||||
{:navigate-from :chats-stack
|
||||
:card-id id
|
||||
:switcher-card {:type shell.constants/private-group-chat-card
|
||||
:card-id id
|
||||
:clock now
|
||||
:screen-id id}}
|
||||
|
||||
constants/community-chat-type
|
||||
{: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)}}})}
|
||||
{: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)}}
|
||||
|
||||
nil))
|
||||
|
||||
:community
|
||||
{: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})}
|
||||
|
||||
{: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))
|
||||
|
||||
(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)))))
|
||||
|
||||
(rf/defn close-switcher-card
|
||||
{:events [:shell/close-switcher-card]}
|
||||
[{:keys [db]} id]
|
||||
{:db (update-in db [:shell/switcher-cards] dissoc id)})
|
||||
[{: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)))
|
||||
|
||||
(rf/defn navigate-to-jump-to
|
||||
{:events [:shell/navigate-to-jump-to]}
|
||||
|
@ -51,9 +51,13 @@
|
||||
:accessibility-label :shell-placeholder-view})
|
||||
|
||||
(def placeholder-image
|
||||
{:margin-top 186
|
||||
:width 120
|
||||
:height 120})
|
||||
{: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})
|
||||
|
||||
(def placeholder-title
|
||||
{:margin-top 20
|
||||
|
@ -47,20 +47,19 @@
|
||||
(i18n/label :t/jump-to)])
|
||||
|
||||
(defn render-card
|
||||
[{:keys [id type content] :as card}]
|
||||
[{:keys [type screen-id] :as card}]
|
||||
(let [card-data (case type
|
||||
shell.constants/one-to-one-chat-card
|
||||
(rf/sub [:shell/one-to-one-chat-card id])
|
||||
(rf/sub [:shell/one-to-one-chat-card screen-id])
|
||||
|
||||
shell.constants/private-group-chat-card
|
||||
(rf/sub [:shell/private-group-chat-card id])
|
||||
(rf/sub [:shell/private-group-chat-card screen-id])
|
||||
|
||||
shell.constants/community-card
|
||||
(if content
|
||||
(rf/sub [:shell/community-channel-card
|
||||
id (get-in content [:data :channel-id])
|
||||
content])
|
||||
(rf/sub [:shell/community-card id]))
|
||||
(rf/sub [:shell/community-card screen-id])
|
||||
|
||||
shell.constants/community-channel-card
|
||||
(rf/sub [:shell/community-channel-card screen-id])
|
||||
|
||||
nil)]
|
||||
[switcher-cards/card (merge card card-data)]))
|
||||
|
@ -10,8 +10,7 @@
|
||||
[status-im2.navigation.state :as state]
|
||||
[status-im2.navigation.view :as views]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf] ;; TODO (14/11/22 flexsurfer) move to status-im2 namespace
|
||||
))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; REGISTER COMPONENT (LAZY)
|
||||
(defn reg-comp
|
||||
|
@ -12,8 +12,7 @@
|
||||
[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] ;; TODO (14/11/22 flexsurfer) move to status-im2
|
||||
;; namespace
|
||||
[status-im2.common.toasts.view :as toasts]
|
||||
[status-im2.navigation.screens :as screens]
|
||||
[status-im2.setup.config :as config]
|
||||
[status-im2.setup.hot-reload :as reloader]))
|
||||
|
@ -1,7 +1,6 @@
|
||||
(ns status-im2.setup.config
|
||||
(:require [clojure.string :as string]
|
||||
[react-native.config :as react-native-config] ;; TODO (14/11/22 flexsurfer move to status-im2
|
||||
;; namespace
|
||||
[react-native.config :as react-native-config]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]))
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
(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]
|
||||
@ -13,8 +14,7 @@
|
||||
[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] ;; TODO (14/11/22 flexsurfer move to
|
||||
;; status-im2 namespace
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
status-im2.contexts.syncing.events
|
||||
status-im2.navigation.core
|
||||
[status-im2.setup.config :as config]
|
||||
@ -22,7 +22,6 @@
|
||||
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))
|
||||
|
||||
@ -32,19 +31,15 @@
|
||||
|
||||
(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 %]))
|
||||
(i18n/init)
|
||||
|
||||
(react-native-languages/add-change-listener
|
||||
#(fn [lang]
|
||||
(i18n/load-language lang i18n-resources/loaded-languages)
|
||||
(i18n/set-language lang)))
|
||||
(react-native-languages/add-change-listener #(fn [lang]
|
||||
(i18n/set-language lang)
|
||||
(i18n-resources/load-language lang)))
|
||||
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
|
||||
(utils.universal-links/initialize)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im2.setup.db
|
||||
(:require [react-native.core :as rn] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
|
||||
(:require [react-native.core :as rn]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]))
|
||||
|
@ -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] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.login.core :as multiaccounts.login]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
|
@ -1,6 +1,78 @@
|
||||
(ns status-im2.setup.i18n-resources
|
||||
(:require [i18n.i18n :as i18n]))
|
||||
(: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})
|
||||
|
||||
(defonce loaded-languages
|
||||
(atom
|
||||
(conj #{:en} i18n/default-device-language)))
|
||||
(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))))
|
||||
|
@ -3,11 +3,12 @@
|
||||
[cljs.test :refer-macros [deftest is]]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[i18n.i18n :as i18n]))
|
||||
[i18n.i18n :as i18n]
|
||||
[status-im2.setup.i18n-resources :as i18n-resources]))
|
||||
|
||||
;; english as source of truth
|
||||
(def labels
|
||||
(set (keys (js->clj (:en i18n/translations-by-locale)
|
||||
(set (keys (js->clj (:en i18n-resources/translations-by-locale)
|
||||
:keywordize-keys
|
||||
true))))
|
||||
|
||||
@ -16,7 +17,7 @@
|
||||
|
||||
(defn labels-for-all-locales
|
||||
[]
|
||||
(->> i18n/translations-by-locale
|
||||
(->> i18n-resources/translations-by-locale
|
||||
(mapcat #(-> % val (js->clj :keywordize-keys true) keys))
|
||||
set))
|
||||
|
||||
@ -1024,14 +1025,14 @@
|
||||
|
||||
;; locales
|
||||
|
||||
(def locales (set (keys i18n/translations-by-locale)))
|
||||
(def locales (set (keys i18n-resources/translations-by-locale)))
|
||||
|
||||
(spec/def ::locale locales)
|
||||
(spec/def ::locales (spec/coll-of ::locale :kind set? :into #{}))
|
||||
|
||||
(defn locale->labels
|
||||
[locale]
|
||||
(-> i18n/translations-by-locale (get locale) (js->clj :keywordize-keys true) keys set))
|
||||
(-> i18n-resources/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]
|
||||
[status-im.test-helpers :as h]
|
||||
[test-helpers.unit :as h]
|
||||
status-im2.subs.activity-center
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -145,6 +145,13 @@
|
||||
(fn [[inputs public-key]]
|
||||
(get inputs (chat.models/profile-chat-topic public-key))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/sending-image
|
||||
:<- [:chats/current-chat-id]
|
||||
:<- [:chat/inputs]
|
||||
(fn [[chat-id inputs]]
|
||||
(get-in inputs [chat-id :metadata :sending-image])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/timeline-chat-input-text
|
||||
:<- [:chats/timeline-chat-input]
|
||||
@ -283,12 +290,6 @@
|
||||
(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]
|
||||
|
@ -102,6 +102,25 @@
|
||||
(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] _]
|
||||
@ -126,7 +145,8 @@
|
||||
(datetime/timestamp)
|
||||
chat-type
|
||||
joined
|
||||
loading-messages?))))))
|
||||
loading-messages?)
|
||||
(albumize-messages))))))
|
||||
|
||||
;;we want to keep data unchanged so react doesn't change component when we leave screen
|
||||
(def memo-profile-messages-stream (atom nil))
|
||||
|
25
src/status_im2/subs/chat/messages_test.cljs
Normal file
25
src/status_im2/subs/chat/messages_test.cljs
Normal file
@ -0,0 +1,25 @@
|
||||
(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))))
|
@ -1,7 +1,7 @@
|
||||
(ns status-im2.subs.communities-test
|
||||
(:require [cljs.test :refer [is testing use-fixtures]]
|
||||
[re-frame.db :as rf-db]
|
||||
[status-im.test-helpers :as h]
|
||||
[test-helpers.unit :as h]
|
||||
status-im2.subs.communities
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@ -135,4 +135,3 @@
|
||||
{:id "0x1" :name "Civilized monkeys"}
|
||||
{:id "0x2" :name "Civilized rats"}]
|
||||
(rf/sub [sub-name])))))
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns status-im2.subs.multiaccount
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[clojure.set :as clojure.set]
|
||||
[clojure.set :as 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])
|
||||
(clojure.set/rename-keys {:name :alias})
|
||||
(set/rename-keys {:name :alias})
|
||||
(multiaccounts/contact-with-names))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
@ -1,21 +1,67 @@
|
||||
(ns status-im2.subs.shell
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im2.common.constants :as status-constants]))
|
||||
[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)))}))))
|
||||
|
||||
(defn get-card-content
|
||||
[chat]
|
||||
[chat communities]
|
||||
(let [last-message (:last-message chat)]
|
||||
(case (:content-type last-message)
|
||||
status-constants/content-type-text
|
||||
{:content-type :text
|
||||
:data (get-in last-message [:content :text])}
|
||||
(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])}
|
||||
|
||||
{:content-type :text
|
||||
:data "Todo: Implement"})))
|
||||
;; 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)})))
|
||||
|
||||
(defn one-to-one-chat-card
|
||||
[contact names chat id]
|
||||
[contact names chat id communities]
|
||||
(let [images (:images contact)
|
||||
profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))]
|
||||
{:title (first names)
|
||||
@ -25,26 +71,20 @@
|
||||
: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)}))
|
||||
:content (get-card-content chat communities)}))
|
||||
|
||||
(defn private-group-chat-card
|
||||
[chat id]
|
||||
[chat id communities]
|
||||
{: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)})
|
||||
:content (get-card-content chat communities)})
|
||||
|
||||
(defn community-card
|
||||
[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)))}))]
|
||||
[community id]
|
||||
(let [profile-picture (community-avatar community)]
|
||||
{:title (:name community)
|
||||
:avatar-params (if profile-picture
|
||||
{:source profile-picture}
|
||||
@ -53,15 +93,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 (or content
|
||||
{:content-type :community-info
|
||||
:data {:type :permission}})}))
|
||||
:content {:community-info {:type :permission}}}))
|
||||
|
||||
(defn community-channel-card
|
||||
[community community-id _ channel-id content]
|
||||
[community community-id channel channel-id]
|
||||
(merge
|
||||
(community-card community community-id content)
|
||||
{:on-press (fn []
|
||||
(community-card community community-id)
|
||||
{:content {:community-channel {:emoji (:emoji channel)
|
||||
:channel-name (str "# " (:name channel))}}
|
||||
: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])
|
||||
@ -78,28 +118,32 @@
|
||||
(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])])
|
||||
(fn [[contact names chat] [_ id]]
|
||||
(one-to-one-chat-card contact names chat 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/reg-sub
|
||||
:shell/private-group-chat-card
|
||||
(fn [[_ id] _]
|
||||
[(re-frame/subscribe [:chats/chat id])])
|
||||
(fn [[chat] [_ id]]
|
||||
(private-group-chat-card chat id)))
|
||||
[(re-frame/subscribe [:chats/chat id])
|
||||
(re-frame/subscribe [:communities])])
|
||||
(fn [[chat communities] [_ id]]
|
||||
(private-group-chat-card chat id communities)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:shell/community-card
|
||||
(fn [[_ id] _]
|
||||
[(re-frame/subscribe [:communities/community id])])
|
||||
(fn [[community] [_ id]]
|
||||
(community-card community id nil)))
|
||||
(community-card community id)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:shell/community-channel-card
|
||||
(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)))
|
||||
(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))))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns status-im2.subs.wallet.wallet-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[re-frame.db :as rf-db]
|
||||
[status-im.test-helpers :as h]
|
||||
[test-helpers.unit :as h]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im2.subs.wallet.wallet :as wallet]
|
||||
[utils.re-frame :as rf]))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.test-helpers
|
||||
(ns test-helpers.unit
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[clojure.string :as string]
|
||||
[clojure.walk :as walk]))
|
||||
@ -34,7 +34,7 @@
|
||||
Example:
|
||||
|
||||
```clojure
|
||||
(require '[status-im.test-helpers :as h])
|
||||
(require '[test-helpers.unit :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
|
||||
`status-im.test-helpers/logs` atom to deref the collection of all logs for the
|
||||
`test-helpers.unit/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 status-im.test-helpers/log-fixture-before
|
||||
:after status-im.test-helpers/log-fixture-after}))
|
||||
{:before test-helpers.unit/log-fixture-before
|
||||
:after test-helpers.unit/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 status-im.test-helpers
|
||||
(ns test-helpers.unit
|
||||
"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 status-im.test-helpers)
|
||||
(:require-macros test-helpers.unit)
|
||||
(:require [re-frame.core :as rf]
|
||||
[re-frame.db :as rf-db]
|
||||
[re-frame.events :as rf-events]
|
@ -1,6 +1,7 @@
|
||||
(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]
|
||||
@ -56,6 +57,7 @@
|
||||
|
||||
;;;; 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]
|
||||
@ -85,6 +87,7 @@
|
||||
(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
|
||||
@ -141,10 +144,14 @@
|
||||
|
||||
(defn timestamp->relative
|
||||
[ms]
|
||||
(let [datetime (t.coerce/from-long ms)]
|
||||
(let [datetime (-> ms
|
||||
t.coerce/from-long
|
||||
(t/plus time-zone-offset))]
|
||||
(cond
|
||||
(today? datetime)
|
||||
(.format ^js (time-fmt) datetime)
|
||||
(str (string/capitalize (i18n/label :t/datetime-today))
|
||||
" "
|
||||
(.format ^js (time-fmt) datetime))
|
||||
|
||||
(within-last-n-days? datetime 1)
|
||||
(str (string/capitalize (i18n/label :t/datetime-yesterday))
|
||||
@ -155,7 +162,7 @@
|
||||
(.format ^js (datetime-within-one-week-fmt) datetime)
|
||||
|
||||
(current-year? datetime)
|
||||
(.format ^js (short-date-fmt) datetime)
|
||||
(.format ^js (short-date-with-time-fmt) datetime)
|
||||
|
||||
(previous-years? datetime)
|
||||
(.format ^js (date-fmt) datetime))))
|
||||
@ -250,3 +257,9 @@
|
||||
(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))))
|
||||
|
@ -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" (datetime/timestamp->relative 163091745000)))
|
||||
(is (= "02 Mar" (datetime/timestamp->relative 163004400000)))
|
||||
(is (= "01 Jan" (datetime/timestamp->relative 157820400000))))
|
||||
(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))))
|
||||
|
||||
(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 (= "3:15 PM" (datetime/timestamp->relative 163696545000)))
|
||||
(is (= "12:00 PM" (datetime/timestamp->relative 163684800000)))
|
||||
(is (= "12:00 AM" (datetime/timestamp->relative 163641600000))))))
|
||||
(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))))))
|
||||
|
||||
#_((deftest day-relative-before-yesterday-force-24H-test
|
||||
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
|
||||
|
@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.117.1a",
|
||||
"commit-sha1": "b4bdfd3df6cf5fb91ab2d0e9f3b38e8d1b9703e5",
|
||||
"src-sha256": "1s50q53p1j5ysnbj88c52zb2rh1ms21pnf6bjc7wja8gzcpih2wl"
|
||||
"version": "v0.117.3",
|
||||
"commit-sha1": "d40290a649133eb7b7f450b5c5b74eec28ba232d",
|
||||
"src-sha256": "140j0gbp8nxzncya9mcpvlxnax5ajfl8c32ih20b29n8j525gw66"
|
||||
}
|
||||
|
@ -1264,27 +1264,20 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
|
||||
self.chat_1.set_reaction(message_from_sender)
|
||||
|
||||
message_sender = self.chat_1.chat_element_by_text(message_from_sender)
|
||||
if message_sender.emojis_below_message() != 1:
|
||||
self.errors.append("Counter of reaction is not updated on your own message!")
|
||||
message_sender.emojis_below_message().wait_for_element_text(1)
|
||||
|
||||
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)
|
||||
if message_receiver.emojis_below_message() != 1:
|
||||
self.errors.append("Counter of reaction is not updated on received message!")
|
||||
message_receiver.emojis_below_message().wait_for_element_text(1, 90)
|
||||
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)
|
||||
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!')
|
||||
message_sender.emojis_below_message().wait_for_element_text(1)
|
||||
message_receiver.emojis_below_message().wait_for_element_text(1, 90)
|
||||
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)
|
||||
@ -1319,64 +1312,67 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
|
||||
self.errors.append(
|
||||
"Message '%s' is missed on Pinned messages list for user %s" % (message, 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)
|
||||
# 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)
|
||||
# )
|
||||
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,6 +267,7 @@ 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")
|
||||
@ -277,7 +278,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="three_2")
|
||||
@pytest.mark.xdist_group(name="two_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="three_1")
|
||||
@pytest.mark.xdist_group(name="one_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="four_2")
|
||||
@pytest.mark.xdist_group(name="two_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="two_1")
|
||||
@pytest.mark.xdist_group(name="one_1")
|
||||
@marks.new_ui_critical
|
||||
class TestDeeplinkOneDeviceNewUI(MultipleSharedDeviceTestCase):
|
||||
|
||||
|
@ -148,10 +148,13 @@ class BaseElement(object):
|
||||
counter = 0
|
||||
self.driver.info("Wait for text element `%s` to be equal to `%s`" % (self.name, text))
|
||||
while True:
|
||||
text_element = self.find_element().text
|
||||
if isinstance(text, int):
|
||||
text_element = int(text_element.strip())
|
||||
if counter >= wait_time:
|
||||
self.driver.fail(message if message else "`%s` is not equal to expected `%s` in %s sec" % (
|
||||
self.find_element().text, text, wait_time))
|
||||
elif self.find_element().text != text:
|
||||
text_element, text, wait_time))
|
||||
elif text_element != text:
|
||||
counter += 10
|
||||
time.sleep(10)
|
||||
else:
|
||||
|
@ -748,7 +748,7 @@ class BaseView(object):
|
||||
|
||||
def tap_by_coordinates(self, x, y):
|
||||
action = TouchAction(self.driver)
|
||||
action.press(None, x, y).perform()
|
||||
action.press(None, x, y).release().perform()
|
||||
|
||||
# Method-helper
|
||||
def write_page_source_to_file(self, full_path_to_file):
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user