Merge pull request #153 from status-im/feature/send-transaction
Send transaction
Former-commit-id: 8148b7e01f
This commit is contained in:
commit
bf02104495
|
@ -138,7 +138,7 @@ dependencies {
|
||||||
compile project(':react-native-fs')
|
compile project(':react-native-fs')
|
||||||
compile project(':react-native-image-crop-picker')
|
compile project(':react-native-image-crop-picker')
|
||||||
//compile(name:'statusgo-android-16', ext:'aar')
|
//compile(name:'statusgo-android-16', ext:'aar')
|
||||||
compile(group: 'status-im', name: 'status-go', version: '0.1.0-201607011545-da53ec', ext: 'aar')
|
compile(group: 'status-im', name: 'status-go', version: 'unlock', ext: 'aar')
|
||||||
|
|
||||||
compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"])
|
compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"])
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class MainApplication extends Application implements ReactApplication {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<ReactPackage> getPackages() {
|
protected List<ReactPackage> getPackages() {
|
||||||
return Arrays.<ReactPackage>asList(
|
return Arrays.asList(
|
||||||
new MainReactPackage(),
|
new MainReactPackage(),
|
||||||
new JailPackage(),
|
new JailPackage(),
|
||||||
new RealmReactPackage(),
|
new RealmReactPackage(),
|
||||||
|
|
|
@ -30,8 +30,7 @@ public class RootUtil {
|
||||||
try {
|
try {
|
||||||
process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
|
process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
if (in.readLine() != null) return true;
|
return in.readLine() != null;
|
||||||
return false;
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.statusim.geth.module;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.RemoteException;
|
||||||
import com.facebook.react.bridge.*;
|
import com.facebook.react.bridge.*;
|
||||||
import com.statusim.geth.service.ConnectorHandler;
|
import com.statusim.geth.service.ConnectorHandler;
|
||||||
import com.statusim.geth.service.GethConnector;
|
import com.statusim.geth.service.GethConnector;
|
||||||
|
@ -13,20 +14,19 @@ import android.util.Log;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class GethModule extends ReactContextBaseJavaModule implements LifecycleEventListener, ConnectorHandler {
|
class GethModule extends ReactContextBaseJavaModule implements LifecycleEventListener, ConnectorHandler {
|
||||||
|
|
||||||
private static final String TAG = "GethModule";
|
private static final String TAG = "GethModule";
|
||||||
|
|
||||||
protected GethConnector geth = null;
|
private GethConnector geth = null;
|
||||||
protected String handlerIdentifier = createIdentifier();
|
|
||||||
|
|
||||||
protected HashMap<String, Callback> startNodeCallbacks = new HashMap<>();
|
private HashMap<String, Callback> startNodeCallbacks = new HashMap<>();
|
||||||
protected HashMap<String, Callback> createAccountCallbacks = new HashMap<>();
|
private HashMap<String, Callback> createAccountCallbacks = new HashMap<>();
|
||||||
protected HashMap<String, Callback> addAccountCallbacks = new HashMap<>();
|
private HashMap<String, Callback> unlockAccountCallbacks = new HashMap<>();
|
||||||
protected HashMap<String, Callback> unlockAccountCallbacks = new HashMap<>();
|
private HashMap<String, Callback> transactionCallbacks = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public GethModule(ReactApplicationContext reactContext) {
|
GethModule(ReactApplicationContext reactContext) {
|
||||||
super(reactContext);
|
super(reactContext);
|
||||||
reactContext.addLifecycleEventListener(this);
|
reactContext.addLifecycleEventListener(this);
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,6 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID() {
|
|
||||||
|
|
||||||
return handlerIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnectorConnected() {
|
public void onConnectorConnected() {
|
||||||
}
|
}
|
||||||
|
@ -89,7 +83,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
Bundle data = message.getData();
|
Bundle data = message.getData();
|
||||||
String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER);
|
String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER);
|
||||||
Log.d(TAG, "callback identifier: " + callbackIdentifier);
|
Log.d(TAG, "callback identifier: " + callbackIdentifier);
|
||||||
Callback callback = null;
|
Callback callback;
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case GethMessages.MSG_NODE_STARTED:
|
case GethMessages.MSG_NODE_STARTED:
|
||||||
Log.d(TAG, "handle startNodeCallbacks size: " + startNodeCallbacks.size());
|
Log.d(TAG, "handle startNodeCallbacks size: " + startNodeCallbacks.size());
|
||||||
|
@ -108,18 +102,20 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
callback.invoke(data.getString("data"));
|
callback.invoke(data.getString("data"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GethMessages.MSG_ACCOUNT_ADDED:
|
|
||||||
callback = addAccountCallbacks.remove(callbackIdentifier);
|
|
||||||
if (callback != null) {
|
|
||||||
callback.invoke(null, "{ \"address\": \"" + data.getString("address") + "\"}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GethMessages.MSG_LOGGED_IN:
|
case GethMessages.MSG_LOGGED_IN:
|
||||||
callback = unlockAccountCallbacks.remove(callbackIdentifier);
|
callback = unlockAccountCallbacks.remove(callbackIdentifier);
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.invoke(data.getString("result"));
|
callback.invoke(data.getString("result"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GethMessages.MSG_TRANSACTION_COMPLETED:
|
||||||
|
callback = transactionCallbacks.remove(callbackIdentifier);
|
||||||
|
String result = data.getString("result");
|
||||||
|
Log.d(TAG, "Send result: " + result + (callback == null));
|
||||||
|
if (callback != null) {
|
||||||
|
callback.invoke(result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
isClaimed = false;
|
isClaimed = false;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +126,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void startNode(Callback callback, Callback onAlreadyRunning) {
|
public void startNode(Callback callback, Callback onAlreadyRunning) {
|
||||||
|
|
||||||
if(GethService.isRunning()){
|
if (GethService.isRunning()) {
|
||||||
onAlreadyRunning.invoke();
|
onAlreadyRunning.invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -197,9 +193,12 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
geth.createAccount(callbackIdentifier, password);
|
geth.createAccount(callbackIdentifier, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
private String createIdentifier() {
|
||||||
public void addAccount(String privateKey, Callback callback) {
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void completeTransaction(String hash, Callback callback) {
|
||||||
Activity currentActivity = getCurrentActivity();
|
Activity currentActivity = getCurrentActivity();
|
||||||
|
|
||||||
if (currentActivity == null) {
|
if (currentActivity == null) {
|
||||||
|
@ -212,13 +211,27 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Complete transaction: " + hash);
|
||||||
String callbackIdentifier = createIdentifier();
|
String callbackIdentifier = createIdentifier();
|
||||||
addAccountCallbacks.put(callbackIdentifier, callback);
|
transactionCallbacks.put(callbackIdentifier, callback);
|
||||||
geth.addAccount(callbackIdentifier, privateKey);
|
|
||||||
|
geth.completeTransaction(callbackIdentifier, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String createIdentifier() {
|
private static Callback signalEventCallback;
|
||||||
return UUID.randomUUID().toString();
|
|
||||||
|
//todo: move this method to GethService
|
||||||
|
public static void signalEvent(String jsonEvent) {
|
||||||
|
Log.d(TAG, "Signal event: " + jsonEvent);
|
||||||
|
if(signalEventCallback != null) {
|
||||||
|
signalEventCallback.invoke(jsonEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void registerSignalEventCallback(Callback callback) {
|
||||||
|
Log.d(TAG, "registerSignalEventCallback");
|
||||||
|
signalEventCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@ package com.statusim.geth.service;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
public interface ConnectorHandler {
|
public interface ConnectorHandler {
|
||||||
|
|
||||||
boolean handleMessage(Message message);
|
boolean handleMessage(Message message);
|
||||||
void onConnectorConnected();
|
void onConnectorConnected();
|
||||||
void onConnectorDisconnected();
|
void onConnectorDisconnected();
|
||||||
String getID();
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -71,22 +71,21 @@ public class GethConnector extends ServiceConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAccount(String callbackIdentifier, String privateKey) {
|
public void completeTransaction(String callbackIdentifier, String hash){
|
||||||
|
|
||||||
if (checkBound()) {
|
if (checkBound()) {
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
data.putString("privateKey", privateKey);
|
data.putString("hash", hash);
|
||||||
Message msg = createMessage(callbackIdentifier, GethMessages.MSG_ADD_ACCOUNT, data);
|
Message msg = createMessage(callbackIdentifier, GethMessages.MSG_COMPLETE_TRANSACTION, data);
|
||||||
try {
|
try {
|
||||||
serviceMessenger.send(msg);
|
serviceMessenger.send(msg);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Exception sending message(addAccount) to service: ", e);
|
Log.e(TAG, "Exception sending message(completeTransaction) to service: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected boolean checkBound() {
|
private boolean checkBound() {
|
||||||
|
|
||||||
if (!isBound) {
|
if (!isBound) {
|
||||||
Log.d(TAG, "GethConnector not bound!");
|
Log.d(TAG, "GethConnector not bound!");
|
||||||
|
@ -95,7 +94,7 @@ public class GethConnector extends ServiceConnector {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Message createMessage(String callbackIdentifier, int idMessage, Bundle data) {
|
private Message createMessage(String callbackIdentifier, int idMessage, Bundle data) {
|
||||||
|
|
||||||
Log.d(TAG, "Client messenger: " + clientMessenger.toString());
|
Log.d(TAG, "Client messenger: " + clientMessenger.toString());
|
||||||
Message msg = Message.obtain(null, idMessage, 0, 0);
|
Message msg = Message.obtain(null, idMessage, 0, 0);
|
||||||
|
|
|
@ -6,7 +6,7 @@ public class GethMessages {
|
||||||
/**
|
/**
|
||||||
* Start the node
|
* Start the node
|
||||||
*/
|
*/
|
||||||
public static final int MSG_START_NODE = 1;
|
static final int MSG_START_NODE = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node started event
|
* Node started event
|
||||||
|
@ -16,7 +16,7 @@ public class GethMessages {
|
||||||
/**
|
/**
|
||||||
* Stop the node
|
* Stop the node
|
||||||
*/
|
*/
|
||||||
public static final int MSG_STOP_NODE = 3;
|
static final int MSG_STOP_NODE = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node stopped event
|
* Node stopped event
|
||||||
|
@ -26,7 +26,7 @@ public class GethMessages {
|
||||||
/**
|
/**
|
||||||
* Unlock an account
|
* Unlock an account
|
||||||
*/
|
*/
|
||||||
public static final int MSG_LOGIN = 5;
|
static final int MSG_LOGIN = 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account unlocked event
|
* Account unlocked event
|
||||||
|
@ -36,7 +36,7 @@ public class GethMessages {
|
||||||
/**
|
/**
|
||||||
* Create an account
|
* Create an account
|
||||||
*/
|
*/
|
||||||
public static final int MSG_CREATE_ACCOUNT = 7;
|
static final int MSG_CREATE_ACCOUNT = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account created event
|
* Account created event
|
||||||
|
@ -44,13 +44,13 @@ public class GethMessages {
|
||||||
public static final int MSG_ACCOUNT_CREATED = 8;
|
public static final int MSG_ACCOUNT_CREATED = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an account
|
* Account complete transaction event
|
||||||
*/
|
*/
|
||||||
public static final int MSG_ADD_ACCOUNT = 9;
|
static final int MSG_COMPLETE_TRANSACTION = 11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account added event
|
* Account complete transaction event
|
||||||
*/
|
*/
|
||||||
public static final int MSG_ACCOUNT_ADDED = 10;
|
public static final int MSG_TRANSACTION_COMPLETED = 11;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,18 @@ public class GethService extends Service {
|
||||||
|
|
||||||
private static final String TAG = "GethService";
|
private static final String TAG = "GethService";
|
||||||
|
|
||||||
private static boolean isGethStarted = false;
|
|
||||||
private static boolean isGethInitialized = false;
|
private static boolean isGethInitialized = false;
|
||||||
private final Handler handler = new Handler();
|
private final Handler handler = new Handler();
|
||||||
|
|
||||||
private static String dataFolder;
|
private static String dataFolder;
|
||||||
|
|
||||||
static class IncomingHandler extends Handler {
|
private static class IncomingHandler extends Handler {
|
||||||
|
|
||||||
private final WeakReference<GethService> service;
|
private final WeakReference<GethService> service;
|
||||||
|
|
||||||
IncomingHandler(GethService service) {
|
IncomingHandler(GethService service) {
|
||||||
|
|
||||||
this.service = new WeakReference<GethService>(service);
|
this.service = new WeakReference<>(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,11 +42,14 @@ public class GethService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Messenger serviceMessenger = new Messenger(new IncomingHandler(this));
|
private final Messenger serviceMessenger = new Messenger(new IncomingHandler(this));
|
||||||
|
|
||||||
|
|
||||||
public static void signalEvent(String jsonEvent) {
|
public static void signalEvent(String jsonEvent) {
|
||||||
System.out.println("\n\n\nIT WOOOOOORKS1111!!!!!!\n\n\n");
|
Log.d(TAG, "Signal event: " + jsonEvent);
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putString("event", jsonEvent);
|
||||||
|
//createAndSendReply(message, GethMessages.MSG_SIGNAL_EVENT, replyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -68,7 +70,6 @@ public class GethService extends Service {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
//TODO: stop geth
|
//TODO: stop geth
|
||||||
stopNode(null);
|
stopNode(null);
|
||||||
isGethStarted = false;
|
|
||||||
isGethInitialized = false;
|
isGethInitialized = false;
|
||||||
Log.d(TAG, "Geth Service stopped !");
|
Log.d(TAG, "Geth Service stopped !");
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ public class GethService extends Service {
|
||||||
return Service.START_STICKY;
|
return Service.START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean handleMessage(Message message) {
|
private boolean handleMessage(Message message) {
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
|
|
||||||
case GethMessages.MSG_START_NODE:
|
case GethMessages.MSG_START_NODE:
|
||||||
|
@ -94,14 +95,14 @@ public class GethService extends Service {
|
||||||
createAccount(message);
|
createAccount(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GethMessages.MSG_ADD_ACCOUNT:
|
|
||||||
addAccount(message);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GethMessages.MSG_LOGIN:
|
case GethMessages.MSG_LOGIN:
|
||||||
login(message);
|
login(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GethMessages.MSG_COMPLETE_TRANSACTION:
|
||||||
|
completeTransaction(message);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,7 @@ public class GethService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startNode(Message message) {
|
private void startNode(Message message) {
|
||||||
if (!isGethInitialized) {
|
if (!isGethInitialized) {
|
||||||
isGethInitialized = true;
|
isGethInitialized = true;
|
||||||
Log.d(TAG, "Client messenger1: " + message.replyTo.toString());
|
Log.d(TAG, "Client messenger1: " + message.replyTo.toString());
|
||||||
|
@ -120,12 +121,12 @@ public class GethService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class StartTask extends AsyncTask<Void, Void, Void> {
|
private class StartTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
protected String callbackIdentifier;
|
String callbackIdentifier;
|
||||||
protected Messenger messenger;
|
Messenger messenger;
|
||||||
|
|
||||||
public StartTask(Messenger messenger, String callbackIdentifier) {
|
StartTask(Messenger messenger, String callbackIdentifier) {
|
||||||
this.messenger = messenger;
|
this.messenger = messenger;
|
||||||
this.callbackIdentifier = callbackIdentifier;
|
this.callbackIdentifier = callbackIdentifier;
|
||||||
}
|
}
|
||||||
|
@ -140,9 +141,8 @@ public class GethService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onGethStarted(Messenger messenger, String callbackIdentifier) {
|
private void onGethStarted(Messenger messenger, String callbackIdentifier) {
|
||||||
Log.d(TAG, "Geth Service started");
|
Log.d(TAG, "Geth Service started");
|
||||||
isGethStarted = true;
|
|
||||||
Message replyMessage = Message.obtain(null, GethMessages.MSG_NODE_STARTED, 0, 0, null);
|
Message replyMessage = Message.obtain(null, GethMessages.MSG_NODE_STARTED, 0, 0, null);
|
||||||
Bundle replyData = new Bundle();
|
Bundle replyData = new Bundle();
|
||||||
Log.d(TAG, "Callback identifier: " + callbackIdentifier);
|
Log.d(TAG, "Callback identifier: " + callbackIdentifier);
|
||||||
|
@ -151,7 +151,7 @@ public class GethService extends Service {
|
||||||
sendReply(messenger, replyMessage);
|
sendReply(messenger, replyMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startGeth() {
|
private void startGeth() {
|
||||||
|
|
||||||
|
|
||||||
File extStore = Environment.getExternalStorageDirectory();
|
File extStore = Environment.getExternalStorageDirectory();
|
||||||
|
@ -160,28 +160,38 @@ public class GethService extends Service {
|
||||||
extStore.getAbsolutePath() + "/ethereum" :
|
extStore.getAbsolutePath() + "/ethereum" :
|
||||||
getApplicationInfo().dataDir + "/ethereum";
|
getApplicationInfo().dataDir + "/ethereum";
|
||||||
Log.d(TAG, "Starting background Geth Service in folder: " + dataFolder);
|
Log.d(TAG, "Starting background Geth Service in folder: " + dataFolder);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final File newFile = new File(dataFolder);
|
final File newFile = new File(dataFolder);
|
||||||
|
// todo handle error?
|
||||||
newFile.mkdir();
|
newFile.mkdir();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "error making folder: " + dataFolder, e);
|
Log.e(TAG, "error making folder: " + dataFolder, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Runnable addPeer = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
Log.w("Geth", "adding peer");
|
||||||
|
Statusgo.addPeer("enode://409772c7dea96fa59a912186ad5bcdb5e51b80556b3fe447d940f99d9eaadb51d4f0ffedb68efad232b52475dd7bd59b51cee99968b3cc79e2d5684b33c4090c@139.162.166.59:30303");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
Statusgo.StartNode(dataFolder);
|
Statusgo.StartNode(dataFolder);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
|
handler.postDelayed(addPeer, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void stopNode(Message message) {
|
private void stopNode(Message message) {
|
||||||
// TODO: stop node
|
// TODO: stop node
|
||||||
|
|
||||||
createAndSendReply(message, GethMessages.MSG_NODE_STOPPED, null);
|
createAndSendReply(message, GethMessages.MSG_NODE_STOPPED, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createAccount(Message message) {
|
private void createAccount(Message message) {
|
||||||
Bundle data = message.getData();
|
Bundle data = message.getData();
|
||||||
String password = data.getString("password");
|
String password = data.getString("password");
|
||||||
// TODO: remove second argument
|
// TODO: remove second argument
|
||||||
|
@ -194,21 +204,7 @@ public class GethService extends Service {
|
||||||
createAndSendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData);
|
createAndSendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addAccount(Message message) {
|
private void login(Message message) {
|
||||||
Bundle data = message.getData();
|
|
||||||
String privateKey = data.getString("privateKey");
|
|
||||||
String password = data.getString("password");
|
|
||||||
// TODO: add account
|
|
||||||
//String address = Statusgo.doAddAccount(privateKey, password);
|
|
||||||
String address = "added account address";
|
|
||||||
Log.d(TAG, "Added account: " + address);
|
|
||||||
|
|
||||||
Bundle replyData = new Bundle();
|
|
||||||
replyData.putString("address", address);
|
|
||||||
createAndSendReply(message, GethMessages.MSG_ACCOUNT_ADDED, replyData);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void login(Message message) {
|
|
||||||
Bundle data = message.getData();
|
Bundle data = message.getData();
|
||||||
String address = data.getString("address");
|
String address = data.getString("address");
|
||||||
String password = data.getString("password");
|
String password = data.getString("password");
|
||||||
|
@ -221,11 +217,24 @@ public class GethService extends Service {
|
||||||
createAndSendReply(message, GethMessages.MSG_LOGGED_IN, replyData);
|
createAndSendReply(message, GethMessages.MSG_LOGGED_IN, replyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void completeTransaction(Message message){
|
||||||
|
Bundle data = message.getData();
|
||||||
|
String hash = data.getString("hash");
|
||||||
|
|
||||||
|
Log.d(TAG, "Before CompleteTransaction: " + hash);
|
||||||
|
String result = Statusgo.CompleteTransaction(hash);
|
||||||
|
Log.d(TAG, "After CompleteTransaction: " + result);
|
||||||
|
|
||||||
|
Bundle replyData = new Bundle();
|
||||||
|
replyData.putString("result", result);
|
||||||
|
createAndSendReply(message, GethMessages.MSG_TRANSACTION_COMPLETED, replyData);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isRunning() {
|
public static boolean isRunning() {
|
||||||
return isGethInitialized;
|
return isGethInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createAndSendReply(Message message, int replyIdMessage, Bundle replyData) {
|
private static void createAndSendReply(Message message, int replyIdMessage, Bundle replyData) {
|
||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -243,7 +252,7 @@ public class GethService extends Service {
|
||||||
sendReply(message.replyTo, replyMessage);
|
sendReply(message.replyTo, replyMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendReply(Messenger messenger, Message message) {
|
private static void sendReply(Messenger messenger, Message message) {
|
||||||
try {
|
try {
|
||||||
messenger.send(message);
|
messenger.send(message);
|
||||||
|
|
||||||
|
|
|
@ -11,39 +11,27 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
public class ServiceConnector {
|
public class ServiceConnector {
|
||||||
|
|
||||||
private static final String TAG = "ServiceConnector";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Incoming message handler. Calls to its binder are sequential!
|
|
||||||
*/
|
|
||||||
protected final IncomingHandler handler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler thread to avoid running on the main UI thread
|
|
||||||
*/
|
|
||||||
protected final HandlerThread handlerThread;
|
|
||||||
|
|
||||||
/** Context of the activity from which this connector was launched */
|
/** Context of the activity from which this connector was launched */
|
||||||
protected Context context;
|
private Context context;
|
||||||
|
|
||||||
/** The class of the service we want to connect to */
|
/** The class of the service we want to connect to */
|
||||||
protected Class serviceClass;
|
private Class serviceClass;
|
||||||
|
|
||||||
/** Flag indicating if the service is bound. */
|
/** Flag indicating if the service is bound. */
|
||||||
protected boolean isBound;
|
boolean isBound;
|
||||||
|
|
||||||
/** Sends messages to the service. */
|
/** Sends messages to the service. */
|
||||||
protected Messenger serviceMessenger = null;
|
Messenger serviceMessenger = null;
|
||||||
|
|
||||||
/** Receives messages from the service. */
|
/** Receives messages from the service. */
|
||||||
protected Messenger clientMessenger = null;
|
Messenger clientMessenger = null;
|
||||||
|
|
||||||
protected ArrayList<ConnectorHandler> handlers = new ArrayList<>();
|
private ArrayList<ConnectorHandler> handlers = new ArrayList<>();
|
||||||
|
|
||||||
/** Handles incoming messages from service. */
|
/** Handles incoming messages from service. */
|
||||||
class IncomingHandler extends Handler {
|
private class IncomingHandler extends Handler {
|
||||||
|
|
||||||
public IncomingHandler(HandlerThread thread) {
|
IncomingHandler(HandlerThread thread) {
|
||||||
|
|
||||||
super(thread.getLooper());
|
super(thread.getLooper());
|
||||||
}
|
}
|
||||||
|
@ -72,7 +60,7 @@ public class ServiceConnector {
|
||||||
/**
|
/**
|
||||||
* Class for interacting with the main interface of the service.
|
* Class for interacting with the main interface of the service.
|
||||||
*/
|
*/
|
||||||
protected ServiceConnection serviceConnection = new ServiceConnection() {
|
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
|
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
|
||||||
|
@ -100,13 +88,14 @@ public class ServiceConnector {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ServiceConnector(Context context, Class serviceClass) {
|
ServiceConnector(Context context, Class serviceClass) {
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.serviceClass = serviceClass;
|
this.serviceClass = serviceClass;
|
||||||
handlerThread = new HandlerThread("HandlerThread");
|
// Handler thread to avoid running on the main UI thread
|
||||||
|
HandlerThread handlerThread = new HandlerThread("HandlerThread");
|
||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
handler = new IncomingHandler(handlerThread);
|
// Incoming message handler. Calls to its binder are sequential!
|
||||||
|
IncomingHandler handler = new IncomingHandler(handlerThread);
|
||||||
clientMessenger = new Messenger(handler);
|
clientMessenger = new Messenger(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 443 B |
Binary file not shown.
After Width: | Height: | Size: 307 B |
Binary file not shown.
After Width: | Height: | Size: 607 B |
Binary file not shown.
After Width: | Height: | Size: 886 B |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
(enable-console-print!)
|
(enable-console-print!)
|
||||||
|
|
||||||
|
(set! js/console.disableYellowBox true)
|
||||||
|
|
||||||
(def cnt (r/atom 0))
|
(def cnt (r/atom 0))
|
||||||
(defn reloader [] @cnt [core/app-root])
|
(defn reloader [] @cnt [core/app-root])
|
||||||
(def root-el (r/as-element [reloader]))
|
(def root-el (r/as-element [reloader]))
|
||||||
|
@ -14,4 +16,4 @@
|
||||||
:heads-up-display false
|
:heads-up-display false
|
||||||
:jsload-callback #(swap! cnt inc))
|
:jsload-callback #(swap! cnt inc))
|
||||||
|
|
||||||
(core/init)
|
(core/init)
|
||||||
|
|
11
project.clj
11
project.clj
|
@ -9,12 +9,15 @@
|
||||||
[re-frame "0.7.0"]
|
[re-frame "0.7.0"]
|
||||||
[prismatic/schema "1.0.4"]
|
[prismatic/schema "1.0.4"]
|
||||||
^{:voom {:repo "git@github.com:status-im/status-lib.git"
|
^{:voom {:repo "git@github.com:status-im/status-lib.git"
|
||||||
:branch "discover-rework"}}
|
:branch "master"}}
|
||||||
[status-im/protocol "0.1.3-20160818_085900-gda79e8e"]
|
[status-im/protocol "0.1.3-20160818_172519-g2f734a6"]
|
||||||
[natal-shell "0.3.0"]
|
[natal-shell "0.3.0"]
|
||||||
[com.andrewmcveigh/cljs-time "0.4.0"]]
|
[com.andrewmcveigh/cljs-time "0.4.0"]
|
||||||
|
[tailrecursion/cljs-priority-map "1.2.0"]
|
||||||
|
[cljsjs/web3 "0.16.0-0"]]
|
||||||
:plugins [[lein-cljsbuild "1.1.1"]
|
:plugins [[lein-cljsbuild "1.1.1"]
|
||||||
[lein-figwheel "0.5.0-2"]]
|
[lein-figwheel "0.5.0-2"]
|
||||||
|
[lein-voom "0.1.0-20160311_203101-g259fbfc"]]
|
||||||
:clean-targets ["target/" "index.ios.js" "index.android.js"]
|
:clean-targets ["target/" "index.ios.js" "index.android.js"]
|
||||||
:aliases {"prod-build" ^{:doc "Recompile code with prod profile."}
|
:aliases {"prod-build" ^{:doc "Recompile code with prod profile."}
|
||||||
["do" "clean"
|
["do" "clean"
|
||||||
|
|
|
@ -260,3 +260,60 @@ status.command({
|
||||||
type: status.types.TEXT
|
type: status.types.TEXT
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function validateBalance(params) {
|
||||||
|
try {
|
||||||
|
var val = web3.toWei(params.value, "ether");
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
errors: [
|
||||||
|
status.components.validationMessage(
|
||||||
|
"Amount",
|
||||||
|
"Amount is not valid number"//err.message
|
||||||
|
)
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var balance = web3.eth.getBalance(params.command.address);
|
||||||
|
if (bn(val).greaterThan(bn(balance))) {
|
||||||
|
return {
|
||||||
|
errors: [
|
||||||
|
status.components.validationMessage(
|
||||||
|
"Amount",
|
||||||
|
"Not enough ETH on balance ("
|
||||||
|
+ web3.fromWei(balance, "ether")
|
||||||
|
+ " ETH)"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendTransaction(params) {
|
||||||
|
var data = {
|
||||||
|
from: params.command.from,
|
||||||
|
to: params.command.to,
|
||||||
|
value: web3.toWei(params.value, "ether")
|
||||||
|
};
|
||||||
|
var hash = web3.eth.sendTransaction(data);
|
||||||
|
|
||||||
|
return {"transaction-hash": hash};
|
||||||
|
}
|
||||||
|
|
||||||
|
status.command({
|
||||||
|
name: "send",
|
||||||
|
color: "#5fc48d",
|
||||||
|
description: "Send transaction",
|
||||||
|
params: [{
|
||||||
|
name: "amount",
|
||||||
|
type: status.types.NUMBER
|
||||||
|
}],
|
||||||
|
preview: function (params) {
|
||||||
|
return status.components.text(
|
||||||
|
{},
|
||||||
|
params.value + " ETH"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handler: sendTransaction,
|
||||||
|
validator: validateBalance
|
||||||
|
});
|
||||||
|
|
|
@ -22,6 +22,7 @@ Command.prototype.create = function (com) {
|
||||||
this.name = com.name;
|
this.name = com.name;
|
||||||
this.description = com.description;
|
this.description = com.description;
|
||||||
this.handler = com.handler;
|
this.handler = com.handler;
|
||||||
|
this["has-handler"] = com.handler != null;
|
||||||
this.validator = com.validator;
|
this.validator = com.validator;
|
||||||
this.color = com.color;
|
this.color = com.color;
|
||||||
this.icon = com.icon;
|
this.icon = com.icon;
|
||||||
|
@ -110,7 +111,7 @@ function validationMessage(titleText, descriptionText) {
|
||||||
};
|
};
|
||||||
var description = status.components.text(descriptionStyle, descriptionText);
|
var description = status.components.text(descriptionStyle, descriptionText);
|
||||||
|
|
||||||
var message = status.components.view(
|
return status.components.view(
|
||||||
{
|
{
|
||||||
backgroundColor: "red",
|
backgroundColor: "red",
|
||||||
height: 61,
|
height: 61,
|
||||||
|
@ -119,8 +120,6 @@ function validationMessage(titleText, descriptionText) {
|
||||||
},
|
},
|
||||||
[title, description]
|
[title, description]
|
||||||
);
|
);
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var status = {
|
var status = {
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
:address address
|
:address address
|
||||||
:name address
|
:name address
|
||||||
:photo-path (identicon public-key)}]
|
:photo-path (identicon public-key)}]
|
||||||
(log/debug "account-created: " account)
|
(log/debug "account-created")
|
||||||
(when (not (str/blank? public-key))
|
(when (not (str/blank? public-key))
|
||||||
(do
|
(do
|
||||||
(dispatch-sync [:add-account account])
|
(dispatch-sync [:add-account account])
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
(defn logged-in [db address]
|
(defn logged-in [db address]
|
||||||
(let [is-login-screen? (= (:view-id db) :login)
|
(let [is-login-screen? (= (:view-id db) :login)
|
||||||
new-account? (not is-login-screen?)]
|
new-account? (not is-login-screen?)]
|
||||||
(log/debug "Logged in: " address)
|
(log/debug "Logged in: ")
|
||||||
(realm/change-account-realm address new-account?
|
(realm/change-account-realm address new-account?
|
||||||
#(if (nil? %)
|
#(if (nil? %)
|
||||||
(initialize-account db address)
|
(initialize-account db address)
|
||||||
|
@ -98,16 +98,17 @@
|
||||||
|
|
||||||
(register-handler
|
(register-handler
|
||||||
:login-account
|
:login-account
|
||||||
(-> (fn [db [_ address password]]
|
(u/side-effect!
|
||||||
(geth/login address password (fn [result]
|
(fn [db [_ address password]]
|
||||||
(let [data (json->clj result)
|
(geth/login address password
|
||||||
error (:error data)
|
(fn [result]
|
||||||
success (zero? (count error))]
|
(let [data (json->clj result)
|
||||||
(log/debug "Logged in account: " address result)
|
error (:error data)
|
||||||
(if success
|
success (zero? (count error))]
|
||||||
(logged-in db address)
|
(log/debug "Logged in account: ")
|
||||||
(dispatch [:set-in [:login :error] error])))))
|
(if success
|
||||||
db)))
|
(logged-in db address)
|
||||||
|
(dispatch [:set-in [:login :error] error]))))))))
|
||||||
|
|
||||||
(defn load-accounts! [db _]
|
(defn load-accounts! [db _]
|
||||||
(let [accounts (->> (accounts/get-accounts)
|
(let [accounts (->> (accounts/get-accounts)
|
||||||
|
@ -120,7 +121,7 @@
|
||||||
|
|
||||||
(defn console-create-account [db _]
|
(defn console-create-account [db _]
|
||||||
(let [msg-id (random/id)]
|
(let [msg-id (random/id)]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id msg-id
|
{:msg-id msg-id
|
||||||
:content {:command (name :keypair)
|
:content {:command (name :keypair)
|
||||||
:content (label :t/keypair-generated)}
|
:content (label :t/keypair-generated)}
|
||||||
|
@ -130,4 +131,4 @@
|
||||||
:to "me"}])
|
:to "me"}])
|
||||||
db))
|
db))
|
||||||
|
|
||||||
(register-handler :console-create-account console-create-account)
|
(register-handler :console-create-account console-create-account)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
[status-im.chat.screen :refer [chat]]
|
[status-im.chat.screen :refer [chat]]
|
||||||
[status-im.accounts.login.screen :refer [login]]
|
[status-im.accounts.login.screen :refer [login]]
|
||||||
[status-im.accounts.screen :refer [accounts]]
|
[status-im.accounts.screen :refer [accounts]]
|
||||||
|
[status-im.transactions.screen :refer [confirm]]
|
||||||
[status-im.chats-list.screen :refer [chats-list]]
|
[status-im.chats-list.screen :refer [chats-list]]
|
||||||
[status-im.new-group.screen :refer [new-group]]
|
[status-im.new-group.screen :refer [new-group]]
|
||||||
[status-im.participants.views.add :refer [new-participants]]
|
[status-im.participants.views.add :refer [new-participants]]
|
||||||
|
@ -98,6 +99,7 @@
|
||||||
:profile-photo-capture profile-photo-capture
|
:profile-photo-capture profile-photo-capture
|
||||||
:accounts accounts
|
:accounts accounts
|
||||||
:login login
|
:login login
|
||||||
|
:confirm confirm
|
||||||
:my-profile my-profile)]
|
:my-profile my-profile)]
|
||||||
[component {:platform-specific {:styles styles
|
[component {:platform-specific {:styles styles
|
||||||
:list-selection-fn show-dialog}}])))})))
|
:list-selection-fn show-dialog}}])))})))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.chat.handlers
|
(ns status-im.chat.handlers
|
||||||
(:require [re-frame.core :refer [enrich after debug dispatch]]
|
(:require-macros [cljs.core.async.macros :as am])
|
||||||
|
(:require [re-frame.core :refer [enrich after debug dispatch path]]
|
||||||
[status-im.models.commands :as commands]
|
[status-im.models.commands :as commands]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[status-im.components.styles :refer [default-chat-color]]
|
[status-im.components.styles :refer [default-chat-color]]
|
||||||
|
@ -20,31 +21,39 @@
|
||||||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||||
[status-im.utils.phone-number :refer [format-phone-number
|
[status-im.utils.phone-number :refer [format-phone-number
|
||||||
valid-mobile-number?]]
|
valid-mobile-number?]]
|
||||||
[status-im.utils.datetime :as time]
|
|
||||||
[status-im.components.jail :as j]
|
[status-im.components.jail :as j]
|
||||||
[status-im.utils.types :refer [json->clj]]
|
[status-im.utils.types :refer [json->clj]]
|
||||||
[status-im.commands.utils :refer [generate-hiccup]]
|
|
||||||
[status-im.chat.handlers.commands :refer [command-prefix]]
|
[status-im.chat.handlers.commands :refer [command-prefix]]
|
||||||
|
[status-im.chat.utils :refer [console? not-console?]]
|
||||||
status-im.chat.handlers.animation
|
status-im.chat.handlers.animation
|
||||||
status-im.chat.handlers.requests
|
status-im.chat.handlers.requests
|
||||||
status-im.chat.handlers.unviewed-messages))
|
status-im.chat.handlers.unviewed-messages
|
||||||
|
status-im.chat.handlers.send-message
|
||||||
|
status-im.chat.handlers.receive-message
|
||||||
|
[cljs.core.async :as a]))
|
||||||
|
|
||||||
(register-handler :set-show-actions
|
(register-handler :set-show-actions
|
||||||
(fn [db [_ show-actions]]
|
(fn [db [_ show-actions]]
|
||||||
(assoc db :show-actions show-actions)))
|
(assoc db :show-actions show-actions)))
|
||||||
|
|
||||||
(register-handler :load-more-messages
|
(register-handler :load-more-messages
|
||||||
(fn [{:keys [current-chat-id] :as db} _]
|
(fn [{:keys [current-chat-id loading-allowed] :as db} _]
|
||||||
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])]
|
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])]
|
||||||
(if all-loaded?
|
(if loading-allowed
|
||||||
db
|
(do (am/go
|
||||||
(let [messages-path [:chats current-chat-id :messages]
|
(<! (a/timeout 400))
|
||||||
messages (get-in db messages-path)
|
(dispatch [:set :loading-allowed true]))
|
||||||
new-messages (messages/get-messages current-chat-id (count messages))
|
(if all-loaded?
|
||||||
all-loaded? (> default-number-of-messages (count new-messages))]
|
db
|
||||||
(-> db
|
(let [messages-path [:chats current-chat-id :messages]
|
||||||
(update-in messages-path concat new-messages)
|
messages (get-in db messages-path)
|
||||||
(assoc-in [:chats current-chat-id :all-loaded?] all-loaded?)))))))
|
new-messages (messages/get-messages current-chat-id (count messages))
|
||||||
|
all-loaded? (> default-number-of-messages (count new-messages))]
|
||||||
|
(-> db
|
||||||
|
(assoc :loading-allowed false)
|
||||||
|
(update-in messages-path concat new-messages)
|
||||||
|
(assoc-in [:chats current-chat-id :all-loaded?] all-loaded?)))))
|
||||||
|
db))))
|
||||||
|
|
||||||
(defn safe-trim [s]
|
(defn safe-trim [s]
|
||||||
(when (string? s)
|
(when (string? s)
|
||||||
|
@ -99,12 +108,6 @@
|
||||||
(dispatch [:set-chat-command (ffirst suggestions)])
|
(dispatch [:set-chat-command (ffirst suggestions)])
|
||||||
(dispatch [::set-text chat-id text]))))
|
(dispatch [::set-text chat-id text]))))
|
||||||
|
|
||||||
(defn console? [s]
|
|
||||||
(= "console" s))
|
|
||||||
|
|
||||||
(def not-console?
|
|
||||||
(complement console?))
|
|
||||||
|
|
||||||
(register-handler :set-chat-input-text
|
(register-handler :set-chat-input-text
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [{:keys [current-chat-id]} [_ text]]
|
(fn [{:keys [current-chat-id]} [_ text]]
|
||||||
|
@ -142,23 +145,6 @@
|
||||||
|
|
||||||
(register-handler ::set-text update-text)
|
(register-handler ::set-text update-text)
|
||||||
|
|
||||||
(defn check-author-direction
|
|
||||||
[db chat-id {:keys [from outgoing] :as message}]
|
|
||||||
(let [previous-message (first (get-in db [:chats chat-id :messages]))]
|
|
||||||
(merge message
|
|
||||||
{:same-author (if previous-message
|
|
||||||
(= (:from previous-message) from)
|
|
||||||
true)
|
|
||||||
:same-direction (if previous-message
|
|
||||||
(= (:outgoing previous-message) outgoing)
|
|
||||||
true)})))
|
|
||||||
|
|
||||||
(defn add-message-to-db
|
|
||||||
[db chat-id message]
|
|
||||||
(let [messages [:chats chat-id :messages]]
|
|
||||||
(update-in db messages conj (assoc message :chat-id chat-id
|
|
||||||
:new? true))))
|
|
||||||
|
|
||||||
(defn set-message-shown
|
(defn set-message-shown
|
||||||
[db chat-id msg-id]
|
[db chat-id msg-id]
|
||||||
(update-in db [:chats chat-id :messages] (fn [messages]
|
(update-in db [:chats chat-id :messages] (fn [messages]
|
||||||
|
@ -172,141 +158,14 @@
|
||||||
(fn [db [_ {:keys [chat-id msg-id]}]]
|
(fn [db [_ {:keys [chat-id msg-id]}]]
|
||||||
(set-message-shown db chat-id msg-id)))
|
(set-message-shown db chat-id msg-id)))
|
||||||
|
|
||||||
(defn default-delivery-status [chat-id]
|
|
||||||
(if (console? chat-id)
|
|
||||||
:seen
|
|
||||||
:pending))
|
|
||||||
|
|
||||||
(defn prepare-message
|
|
||||||
[{:keys [identity current-chat-id] :as db} _]
|
|
||||||
(let [text (get-in db [:chats current-chat-id :input-text])
|
|
||||||
[command] (suggestions/check-suggestion db (str text " "))
|
|
||||||
message (check-author-direction
|
|
||||||
db current-chat-id
|
|
||||||
{:msg-id (random/id)
|
|
||||||
:chat-id current-chat-id
|
|
||||||
:content text
|
|
||||||
:to current-chat-id
|
|
||||||
:from identity
|
|
||||||
:content-type text-content-type
|
|
||||||
:delivery-status (default-delivery-status current-chat-id)
|
|
||||||
:outgoing true
|
|
||||||
:timestamp (time/now-ms)})]
|
|
||||||
_ (.log js/console "WOW3")
|
|
||||||
(if command
|
|
||||||
(commands/set-command-input db :commands command)
|
|
||||||
(assoc db :new-message (when-not (str/blank? text) message)))))
|
|
||||||
|
|
||||||
(defn prepare-command
|
|
||||||
[identity chat-id {:keys [preview preview-string content command to-message]}]
|
|
||||||
(let [content {:command (command :name)
|
|
||||||
:content content}]
|
|
||||||
{:msg-id (random/id)
|
|
||||||
:from identity
|
|
||||||
:to chat-id
|
|
||||||
:content content
|
|
||||||
:content-type content-type-command
|
|
||||||
:delivery-status (default-delivery-status chat-id)
|
|
||||||
:outgoing true
|
|
||||||
:preview preview-string
|
|
||||||
:rendered-preview preview
|
|
||||||
:to-message to-message}))
|
|
||||||
|
|
||||||
(defn prepare-staged-commans
|
|
||||||
[{:keys [current-chat-id identity] :as db} _]
|
|
||||||
(let [staged-commands (get-in db [:chats current-chat-id :staged-commands])]
|
|
||||||
(->> staged-commands
|
|
||||||
(map #(prepare-command identity current-chat-id %))
|
|
||||||
;todo this is wrong :(
|
|
||||||
(map #(check-author-direction db current-chat-id %))
|
|
||||||
(assoc db :new-commands))))
|
|
||||||
|
|
||||||
(defn add-message
|
|
||||||
[{:keys [new-message current-chat-id] :as db}]
|
|
||||||
(if new-message
|
|
||||||
(add-message-to-db db current-chat-id new-message)
|
|
||||||
db))
|
|
||||||
|
|
||||||
(defn add-commands
|
|
||||||
[{:keys [new-commands current-chat-id] :as db}]
|
|
||||||
(reduce
|
|
||||||
#(add-message-to-db %1 current-chat-id %2)
|
|
||||||
db
|
|
||||||
new-commands))
|
|
||||||
|
|
||||||
(defn clear-input
|
|
||||||
[{:keys [current-chat-id new-message] :as db} _]
|
|
||||||
(if new-message
|
|
||||||
(assoc-in db [:chats current-chat-id :input-text] nil)
|
|
||||||
db))
|
|
||||||
|
|
||||||
(defn clear-staged-commands
|
|
||||||
[{:keys [current-chat-id] :as db} _]
|
|
||||||
(assoc-in db [:chats current-chat-id :staged-commands] []))
|
|
||||||
|
|
||||||
(defn send-message!
|
|
||||||
[{:keys [new-message current-chat-id] :as db} _]
|
|
||||||
(when (and new-message (not-console? current-chat-id))
|
|
||||||
(let [{:keys [group-chat]} (get-in db [:chats current-chat-id])
|
|
||||||
message (select-keys new-message [:content :msg-id])]
|
|
||||||
(if group-chat
|
|
||||||
(api/send-group-user-msg (assoc message :group-id current-chat-id))
|
|
||||||
(api/send-user-msg (assoc message :to current-chat-id))))))
|
|
||||||
|
|
||||||
(defn save-message-to-realm!
|
|
||||||
[{:keys [new-message current-chat-id]} _]
|
|
||||||
(when new-message
|
|
||||||
(messages/save-message current-chat-id new-message)))
|
|
||||||
|
|
||||||
(defn save-commands-to-realm!
|
|
||||||
[{:keys [new-commands current-chat-id]} _]
|
|
||||||
(doseq [new-command new-commands]
|
|
||||||
(messages/save-message
|
|
||||||
current-chat-id
|
|
||||||
(dissoc new-command :rendered-preview :to-message))))
|
|
||||||
|
|
||||||
(defn dispatch-responded-requests!
|
|
||||||
[{:keys [new-commands current-chat-id]} _]
|
|
||||||
(doseq [{:keys [to-message]} new-commands]
|
|
||||||
(when to-message
|
|
||||||
(dispatch [:request-answered! current-chat-id to-message]))))
|
|
||||||
|
|
||||||
(defn invoke-commands-handlers!
|
|
||||||
[{:keys [new-commands current-chat-id]}]
|
|
||||||
(doseq [{:keys [content] :as com} new-commands]
|
|
||||||
(let [{:keys [command content]} content
|
|
||||||
type (:type command)
|
|
||||||
path [(if (= :command type) :commands :responses)
|
|
||||||
command
|
|
||||||
:handler]
|
|
||||||
params {:value content}]
|
|
||||||
(j/call current-chat-id
|
|
||||||
path
|
|
||||||
params
|
|
||||||
#(dispatch [:command-handler! com %])))))
|
|
||||||
|
|
||||||
(register-handler :send-chat-msg
|
|
||||||
(-> prepare-message
|
|
||||||
((enrich prepare-staged-commans))
|
|
||||||
((enrich add-message))
|
|
||||||
((enrich add-commands))
|
|
||||||
((enrich clear-input))
|
|
||||||
((enrich clear-staged-commands))
|
|
||||||
((after send-message!))
|
|
||||||
((after save-message-to-realm!))
|
|
||||||
((after save-commands-to-realm!))
|
|
||||||
((after dispatch-responded-requests!))
|
|
||||||
;; todo maybe it is better to track if it was handled or not
|
|
||||||
((after invoke-commands-handlers!))))
|
|
||||||
|
|
||||||
(register-handler :init-console-chat
|
(register-handler :init-console-chat
|
||||||
(fn [db [_]]
|
(fn [db [_]]
|
||||||
(sign-up-service/init db)))
|
(sign-up-service/init db)))
|
||||||
|
|
||||||
(register-handler :save-password
|
(register-handler :save-password
|
||||||
(fn [db [_ password]]
|
(fn [db [_ password]]
|
||||||
(dispatch [:create-account password])
|
|
||||||
(sign-up-service/save-password password)
|
(sign-up-service/save-password password)
|
||||||
|
(dispatch [:create-account password])
|
||||||
(assoc db :password-saved true)))
|
(assoc db :password-saved true)))
|
||||||
|
|
||||||
(register-handler :sign-up
|
(register-handler :sign-up
|
||||||
|
@ -372,35 +231,6 @@
|
||||||
(after #(dispatch [:load-unviewed-messages!]))
|
(after #(dispatch [:load-unviewed-messages!]))
|
||||||
((enrich initialize-chats) load-chats!))
|
((enrich initialize-chats) load-chats!))
|
||||||
|
|
||||||
(defn store-message!
|
|
||||||
[{:keys [new-message]} [_ {chat-id :from}]]
|
|
||||||
(messages/save-message chat-id new-message))
|
|
||||||
|
|
||||||
(defn dispatch-request!
|
|
||||||
[{:keys [new-message]} [_ {chat-id :from}]]
|
|
||||||
(when (= (:content-type new-message) content-type-command-request)
|
|
||||||
(dispatch [:add-request chat-id new-message])))
|
|
||||||
|
|
||||||
(defn receive-message
|
|
||||||
[db [_ {chat-id :from :as message}]]
|
|
||||||
(let [message' (-> db
|
|
||||||
(check-author-direction chat-id message)
|
|
||||||
(assoc :delivery-status :pending))]
|
|
||||||
(-> db
|
|
||||||
(add-message-to-db chat-id message')
|
|
||||||
(assoc :new-message message'))))
|
|
||||||
|
|
||||||
(defn dispatch-unviewed-message!
|
|
||||||
[{:keys [new-message]} [_ {chat-id :from}]]
|
|
||||||
(let [{:keys [msg-id]} new-message]
|
|
||||||
(dispatch [:add-unviewed-message chat-id msg-id])))
|
|
||||||
|
|
||||||
(register-handler :received-msg
|
|
||||||
[(after store-message!)
|
|
||||||
(after dispatch-request!)
|
|
||||||
(after dispatch-unviewed-message!)]
|
|
||||||
receive-message)
|
|
||||||
|
|
||||||
(register-handler :group-received-msg
|
(register-handler :group-received-msg
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [_ [_ {chat-id :group-id :as msg}]]
|
(fn [_ [_ {chat-id :group-id :as msg}]]
|
||||||
|
@ -412,6 +242,7 @@
|
||||||
messages (get-in db [:chats chat-id :messages])
|
messages (get-in db [:chats chat-id :messages])
|
||||||
db' (assoc db :current-chat-id chat-id)]
|
db' (assoc db :current-chat-id chat-id)]
|
||||||
(dispatch [:load-requests! chat-id])
|
(dispatch [:load-requests! chat-id])
|
||||||
|
(dispatch [:load-commands! chat-id])
|
||||||
(if (seq messages)
|
(if (seq messages)
|
||||||
db'
|
db'
|
||||||
(-> db'
|
(-> db'
|
||||||
|
@ -419,15 +250,15 @@
|
||||||
init-chat))))
|
init-chat))))
|
||||||
|
|
||||||
(defn prepare-chat
|
(defn prepare-chat
|
||||||
[{:keys [contacts] :as db} [_ contcat-id]]
|
[{:keys [contacts] :as db} [_ contact-id]]
|
||||||
(let [name (get-in contacts [contcat-id :name])
|
(let [name (get-in contacts [contact-id :name])
|
||||||
chat {:chat-id contcat-id
|
chat {:chat-id contact-id
|
||||||
:name name
|
:name (or name contact-id)
|
||||||
:color default-chat-color
|
:color default-chat-color
|
||||||
:group-chat false
|
:group-chat false
|
||||||
:is-active true
|
:is-active true
|
||||||
:timestamp (.getTime (js/Date.))
|
:timestamp (.getTime (js/Date.))
|
||||||
:contacts [{:identity contcat-id}]
|
:contacts [{:identity contact-id}]
|
||||||
:dapp-url nil
|
:dapp-url nil
|
||||||
:dapp-hash nil}]
|
:dapp-hash nil}]
|
||||||
(assoc db :new-chat chat)))
|
(assoc db :new-chat chat)))
|
||||||
|
@ -451,6 +282,11 @@
|
||||||
((after save-chat!))
|
((after save-chat!))
|
||||||
((after open-chat!))))
|
((after open-chat!))))
|
||||||
|
|
||||||
|
(register-handler :add-chat
|
||||||
|
(-> prepare-chat
|
||||||
|
((enrich add-chat))
|
||||||
|
((after save-chat!))))
|
||||||
|
|
||||||
(register-handler :switch-command-suggestions!
|
(register-handler :switch-command-suggestions!
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [db]
|
(fn [db]
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
suggestion? (get-in db [:has-suggestions? current-chat-id])
|
suggestion? (get-in db [:has-suggestions? current-chat-id])
|
||||||
custom-errors (get-in db [:custom-validation-errors current-chat-id])
|
custom-errors (get-in db [:custom-validation-errors current-chat-id])
|
||||||
validation-height (if (or (seq errors) (seq custom-errors))
|
validation-height (if (or (seq errors) (seq custom-errors))
|
||||||
request-info-height
|
(+ suggestions-header-height request-info-height)
|
||||||
0)]
|
0)]
|
||||||
(+ validation-height
|
(+ validation-height
|
||||||
(if (= :response type)
|
(if (= :response type)
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[status-im.commands.utils :as cu]
|
[status-im.commands.utils :as cu]
|
||||||
[status-im.utils.phone-number :as pn]
|
[status-im.utils.phone-number :as pn]
|
||||||
[status-im.i18n :as i18n]))
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.datetime :as time]
|
||||||
|
[status-im.utils.random :as random]))
|
||||||
|
|
||||||
(def command-prefix "c ")
|
(def command-prefix "c ")
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@
|
||||||
|
|
||||||
(defn invoke-command-preview!
|
(defn invoke-command-preview!
|
||||||
[{:keys [staged-command]} [_ chat-id]]
|
[{:keys [staged-command]} [_ chat-id]]
|
||||||
(let [{:keys [command content]} staged-command
|
(let [{:keys [command content id]} staged-command
|
||||||
{:keys [name type]} command
|
{:keys [name type]} command
|
||||||
path [(if (= :command type) :commands :responses)
|
path [(if (= :command type) :commands :responses)
|
||||||
name
|
name
|
||||||
|
@ -70,7 +72,7 @@
|
||||||
(j/call chat-id
|
(j/call chat-id
|
||||||
path
|
path
|
||||||
params
|
params
|
||||||
#(dispatch [:command-preview chat-id %]))))
|
#(dispatch [:command-preview chat-id id %]))))
|
||||||
|
|
||||||
(defn command-input
|
(defn command-input
|
||||||
([{:keys [current-chat-id] :as db}]
|
([{:keys [current-chat-id] :as db}]
|
||||||
|
@ -102,7 +104,8 @@
|
||||||
path [(if (= :command type) :commands :responses)
|
path [(if (= :command type) :commands :responses)
|
||||||
name
|
name
|
||||||
:validator]
|
:validator]
|
||||||
params {:value content}]
|
params {:value content
|
||||||
|
:command data}]
|
||||||
(j/call chat-id
|
(j/call chat-id
|
||||||
path
|
path
|
||||||
params
|
params
|
||||||
|
@ -110,13 +113,14 @@
|
||||||
|
|
||||||
(register-handler :stage-command
|
(register-handler :stage-command
|
||||||
(after start-validate!)
|
(after start-validate!)
|
||||||
(fn [{:keys [current-chat-id] :as db}]
|
(fn [{:keys [current-chat-id current-account-id] :as db}]
|
||||||
(let [{:keys [command content]} (command-input db)
|
(let [{:keys [command content]} (command-input db)
|
||||||
content' (content-by-command command content)]
|
content' (content-by-command command content)]
|
||||||
(-> db
|
(-> db
|
||||||
(assoc ::command {:content content'
|
(assoc ::command {:content content'
|
||||||
:command command
|
:command command
|
||||||
:chat-id current-chat-id})
|
:chat-id current-chat-id
|
||||||
|
:address current-account-id})
|
||||||
(assoc-in [:disable-staging current-chat-id] true)))))
|
(assoc-in [:disable-staging current-chat-id] true)))))
|
||||||
|
|
||||||
(register-handler ::finish-command-staging
|
(register-handler ::finish-command-staging
|
||||||
|
@ -128,7 +132,9 @@
|
||||||
content' (content-by-command command content)
|
content' (content-by-command command content)
|
||||||
command-info {:command command
|
command-info {:command command
|
||||||
:content content'
|
:content content'
|
||||||
:to-message to-msg-id}]
|
:to-message to-msg-id
|
||||||
|
:created-at (time/now-ms)
|
||||||
|
:id (random/id)}]
|
||||||
(-> db
|
(-> db
|
||||||
(commands/stage-command command-info)
|
(commands/stage-command command-info)
|
||||||
(assoc :staged-command command-info)
|
(assoc :staged-command command-info)
|
||||||
|
@ -172,14 +178,19 @@
|
||||||
(fn [db]
|
(fn [db]
|
||||||
(dissoc db :validation-errors :custom-validation-errors)))
|
(dissoc db :validation-errors :custom-validation-errors)))
|
||||||
|
|
||||||
|
(defn dispatch-error!
|
||||||
|
[chat-id title description]
|
||||||
|
(letfn [(wrap-params [p] (if (seqable? p) p [p]))]
|
||||||
|
(dispatch [::set-validation-error
|
||||||
|
chat-id
|
||||||
|
{:title (apply i18n/label (wrap-params title))
|
||||||
|
:description (apply i18n/label (wrap-params description))}])))
|
||||||
|
|
||||||
(def validation-handlers
|
(def validation-handlers
|
||||||
{:phone (fn [chat-id [number]]
|
{:phone (fn [chat-id [number]]
|
||||||
(if (pn/valid-mobile-number? number)
|
(if (pn/valid-mobile-number? number)
|
||||||
(dispatch [::finish-command-staging chat-id])
|
(dispatch [::finish-command-staging chat-id])
|
||||||
(dispatch [::set-validation-error
|
(dispatch-error! chat-id :t/phone-number :t/invalid-phone)))})
|
||||||
chat-id
|
|
||||||
{:title (i18n/label :t/phone-number)
|
|
||||||
:description (i18n/label :t/invalid-phone)}])))})
|
|
||||||
|
|
||||||
(defn validator [name]
|
(defn validator [name]
|
||||||
(validation-handlers (keyword name)))
|
(validation-handlers (keyword name)))
|
||||||
|
@ -190,7 +201,6 @@
|
||||||
(when-let [handler (validator name)]
|
(when-let [handler (validator name)]
|
||||||
(handler chat-id params)))))
|
(handler chat-id params)))))
|
||||||
|
|
||||||
|
|
||||||
(register-handler ::set-validation-error
|
(register-handler ::set-validation-error
|
||||||
(after #(dispatch [:fix-response-height]))
|
(after #(dispatch [:fix-response-height]))
|
||||||
(fn [db [_ chat-id error]]
|
(fn [db [_ chat-id error]]
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
(ns status-im.chat.handlers.receive-message
|
||||||
|
(:require [status-im.utils.handlers :refer [register-handler] :as u]
|
||||||
|
[re-frame.core :refer [enrich after debug dispatch path]]
|
||||||
|
[status-im.models.messages :as messages]
|
||||||
|
[status-im.chat.utils :as cu]
|
||||||
|
[status-im.commands.utils :refer [generate-hiccup]]
|
||||||
|
[status-im.constants :refer [content-type-command-request]]
|
||||||
|
[cljs.reader :refer [read-string]]
|
||||||
|
[status-im.models.chats :as c]))
|
||||||
|
|
||||||
|
(defn check-previev [{:keys [content] :as message}]
|
||||||
|
(if-let [preview (:preview content)]
|
||||||
|
(let [rendered-preview (generate-hiccup (read-string preview))]
|
||||||
|
(assoc message
|
||||||
|
:preview preview
|
||||||
|
:rendered-preview rendered-preview))
|
||||||
|
message))
|
||||||
|
|
||||||
|
(defn store-message [{chat-id :from :as message}]
|
||||||
|
(messages/save-message chat-id (dissoc message :rendered-preview :new?)))
|
||||||
|
|
||||||
|
(register-handler :received-message
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [chats] :as db} [_ {chat-id :from :keys [msg-id] :as message}]]
|
||||||
|
(let [same-message (messages/get-message msg-id)]
|
||||||
|
(when-not same-message
|
||||||
|
(let [message' (assoc (->> message
|
||||||
|
(cu/check-author-direction db chat-id)
|
||||||
|
(check-previev))
|
||||||
|
:delivery-status :pending)]
|
||||||
|
(store-message message')
|
||||||
|
(when-not (c/chat-exists? chat-id)
|
||||||
|
(dispatch [:add-chat chat-id]))
|
||||||
|
(dispatch [::add-message message'])
|
||||||
|
(when (= (:content-type message') content-type-command-request)
|
||||||
|
(dispatch [:add-request chat-id message']))
|
||||||
|
(dispatch [:add-unviewed-message chat-id msg-id])))))))
|
||||||
|
|
||||||
|
(register-handler ::add-message
|
||||||
|
(fn [db [_ {chat-id :from :keys [new?] :as message}]]
|
||||||
|
(cu/add-message-to-db db chat-id message new?)))
|
|
@ -1,9 +1,9 @@
|
||||||
(ns status-im.chat.handlers.requests
|
(ns status-im.chat.handlers.requests
|
||||||
(:require [re-frame.core :refer [after dispatch enrich]]
|
(:require [re-frame.core :refer [after dispatch enrich]]
|
||||||
[status-im.utils.handlers :refer [register-handler]]
|
[status-im.utils.handlers :refer [register-handler]]
|
||||||
[status-im.persistence.realm.core :as realm]
|
|
||||||
[status-im.models.requests :as requests]
|
[status-im.models.requests :as requests]
|
||||||
[status-im.utils.handlers :as u]))
|
[status-im.utils.handlers :refer [register-handler] :as u]
|
||||||
|
[status-im.persistence.realm.core :as realm]))
|
||||||
|
|
||||||
(defn store-request!
|
(defn store-request!
|
||||||
[{:keys [new-request] :as db}]
|
[{:keys [new-request] :as db}]
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
(ns status-im.chat.handlers.send-message
|
||||||
|
(:require [status-im.utils.handlers :refer [register-handler] :as u]
|
||||||
|
[clojure.string :as s]
|
||||||
|
[status-im.models.messages :as messages]
|
||||||
|
[status-im.components.jail :as j]
|
||||||
|
[status-im.utils.random :as random]
|
||||||
|
[status-im.utils.datetime :as time]
|
||||||
|
[re-frame.core :refer [enrich after debug dispatch path]]
|
||||||
|
[status-im.chat.suggestions :as suggestions]
|
||||||
|
[status-im.models.commands :as commands]
|
||||||
|
[status-im.chat.utils :as cu]
|
||||||
|
[status-im.constants :refer [text-content-type
|
||||||
|
content-type-command
|
||||||
|
content-type-command-request
|
||||||
|
default-number-of-messages]]
|
||||||
|
[status-im.protocol.api :as api]))
|
||||||
|
|
||||||
|
(defn default-delivery-status [chat-id]
|
||||||
|
(if (cu/console? chat-id)
|
||||||
|
:seen
|
||||||
|
:pending))
|
||||||
|
|
||||||
|
(defn prepare-message
|
||||||
|
[{:keys [identity current-chat-id] :as db} _]
|
||||||
|
(let [text (get-in db [:chats current-chat-id :input-text])
|
||||||
|
[command] (suggestions/check-suggestion db (str text " "))
|
||||||
|
message (cu/check-author-direction
|
||||||
|
db current-chat-id
|
||||||
|
{:msg-id (random/id)
|
||||||
|
:chat-id current-chat-id
|
||||||
|
:content text
|
||||||
|
:to current-chat-id
|
||||||
|
:from identity
|
||||||
|
:content-type text-content-type
|
||||||
|
:delivery-status (default-delivery-status current-chat-id)
|
||||||
|
:outgoing true
|
||||||
|
:timestamp (time/now-ms)})]
|
||||||
|
(if command
|
||||||
|
(commands/set-command-input db :commands command)
|
||||||
|
(assoc db :new-message (when-not (s/blank? text) message)))))
|
||||||
|
|
||||||
|
(defn prepare-command
|
||||||
|
[identity chat-id {:keys [preview preview-string content command to-message]}]
|
||||||
|
(let [content {:command (command :name)
|
||||||
|
:content content}]
|
||||||
|
{:msg-id (random/id)
|
||||||
|
:from identity
|
||||||
|
:to chat-id
|
||||||
|
:content (assoc content :preview preview-string)
|
||||||
|
:content-type content-type-command
|
||||||
|
:delivery-status (default-delivery-status chat-id)
|
||||||
|
:outgoing true
|
||||||
|
:preview preview-string
|
||||||
|
:rendered-preview preview
|
||||||
|
:to-message to-message
|
||||||
|
:type (:type command)
|
||||||
|
:has-handler (:has-handler command)}))
|
||||||
|
|
||||||
|
(register-handler :send-chat-msg
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [current-chat-id identity current-account-id] :as db}]
|
||||||
|
(let [staged-commands (vals (get-in db [:chats current-chat-id :staged-commands]))
|
||||||
|
text (get-in db [:chats current-chat-id :input-text])
|
||||||
|
data {:commands staged-commands
|
||||||
|
:message text
|
||||||
|
:chat-id current-chat-id
|
||||||
|
:identity identity
|
||||||
|
:address current-account-id}]
|
||||||
|
(dispatch [:clear-input current-chat-id])
|
||||||
|
(cond
|
||||||
|
(seq staged-commands)
|
||||||
|
(dispatch [::check-commands-handlers! data])
|
||||||
|
(not (s/blank? text))
|
||||||
|
(dispatch [::prepare-message data]))))))
|
||||||
|
|
||||||
|
|
||||||
|
(register-handler ::check-commands-handlers!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ {:keys [commands message] :as params}]]
|
||||||
|
(doseq [{:keys [command] :as message} commands]
|
||||||
|
(let [params' (assoc params :command message)]
|
||||||
|
(if (:pending message)
|
||||||
|
(dispatch [:navigate-to :confirm])
|
||||||
|
(if (:has-handler command)
|
||||||
|
(dispatch [::invoke-command-handlers! params'])
|
||||||
|
(dispatch [:prepare-command! params'])))))
|
||||||
|
(when-not (s/blank? message)
|
||||||
|
(dispatch [::prepare-message params])))))
|
||||||
|
|
||||||
|
(register-handler :clear-input
|
||||||
|
(path :chats)
|
||||||
|
(fn [db [_ chat-id]]
|
||||||
|
(assoc-in db [chat-id :input-text] nil)))
|
||||||
|
|
||||||
|
(register-handler :prepare-command!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ {:keys [chat-id command identity] :as params}]]
|
||||||
|
(let [command' (->> command
|
||||||
|
(prepare-command identity chat-id)
|
||||||
|
(cu/check-author-direction db chat-id))]
|
||||||
|
(dispatch [::clear-command chat-id (:id command)])
|
||||||
|
(dispatch [::send-command! (assoc params :command command')])))))
|
||||||
|
|
||||||
|
(register-handler ::clear-command
|
||||||
|
(fn [db [_ chat-id id]]
|
||||||
|
(update-in db [:chats chat-id :staged-commands] dissoc id)))
|
||||||
|
|
||||||
|
(register-handler ::send-command!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ params]]
|
||||||
|
(dispatch [::add-command params])
|
||||||
|
(dispatch [::save-command! params])
|
||||||
|
(dispatch [::dispatch-responded-requests! params])
|
||||||
|
(dispatch [::send-command-protocol! params]))))
|
||||||
|
|
||||||
|
(register-handler ::add-command
|
||||||
|
(after (fn [_ [_ {:keys [handler]}]]
|
||||||
|
(when handler (handler))))
|
||||||
|
(fn [db [_ {:keys [chat-id command]}]]
|
||||||
|
(cu/add-message-to-db db chat-id command)))
|
||||||
|
|
||||||
|
(register-handler ::save-command!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ {:keys [command chat-id]}]]
|
||||||
|
(messages/save-message
|
||||||
|
chat-id
|
||||||
|
(dissoc command :rendered-preview :to-message :has-handler)))))
|
||||||
|
|
||||||
|
(register-handler ::dispatch-responded-requests!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ {:keys [command chat-id]}]]
|
||||||
|
(let [{:keys [to-message]} command]
|
||||||
|
(when to-message
|
||||||
|
(dispatch [:request-answered! chat-id to-message]))))))
|
||||||
|
|
||||||
|
(register-handler ::invoke-command-handlers!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ {:keys [chat-id address] :as parameters}]]
|
||||||
|
(let [{:keys [command content]} (:command parameters)
|
||||||
|
{:keys [type name]} command
|
||||||
|
path [(if (= :command type) :commands :responses)
|
||||||
|
name
|
||||||
|
:handler]
|
||||||
|
to (get-in db [:contacts chat-id :address])
|
||||||
|
params {:value content
|
||||||
|
:command {:from address
|
||||||
|
:to to}}]
|
||||||
|
(j/call chat-id
|
||||||
|
path
|
||||||
|
params
|
||||||
|
#(dispatch [:command-handler! chat-id parameters %]))))))
|
||||||
|
|
||||||
|
(register-handler ::prepare-message
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ {:keys [chat-id identity message] :as params}]]
|
||||||
|
(let [message' (cu/check-author-direction
|
||||||
|
db chat-id
|
||||||
|
{:msg-id (random/id)
|
||||||
|
:chat-id chat-id
|
||||||
|
:content message
|
||||||
|
:to chat-id
|
||||||
|
:from identity
|
||||||
|
:content-type text-content-type
|
||||||
|
:delivery-status (default-delivery-status chat-id)
|
||||||
|
:outgoing true
|
||||||
|
:timestamp (time/now-ms)})
|
||||||
|
params' (assoc params :message message')]
|
||||||
|
(dispatch [::add-message params'])
|
||||||
|
(dispatch [::save-message! params'])
|
||||||
|
(dispatch [::send-message! params'])))))
|
||||||
|
|
||||||
|
(register-handler ::add-message
|
||||||
|
(fn [db [_ {:keys [chat-id message]}]]
|
||||||
|
(cu/add-message-to-db db chat-id message)))
|
||||||
|
|
||||||
|
(register-handler ::save-message!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ {:keys [chat-id message]}]]
|
||||||
|
(messages/save-message chat-id message))))
|
||||||
|
|
||||||
|
(register-handler ::send-message!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ {:keys [message chat-id]}]]
|
||||||
|
(when (and message (cu/not-console? chat-id))
|
||||||
|
(let [{:keys [group-chat]} (get-in db [:chats chat-id])
|
||||||
|
message' (select-keys message [:content :msg-id])]
|
||||||
|
(if group-chat
|
||||||
|
(api/send-group-user-msg (assoc message' :group-id chat-id))
|
||||||
|
(api/send-user-msg (assoc message' :to chat-id))))))))
|
||||||
|
|
||||||
|
(register-handler ::send-command-protocol!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ {:keys [chat-id command]}]]
|
||||||
|
(let [{:keys [content]} command]
|
||||||
|
(when (cu/not-console? chat-id)
|
||||||
|
(let [{:keys [group-chat]} (get-in db [:chats chat-id])
|
||||||
|
message {:content content
|
||||||
|
:content-type content-type-command}]
|
||||||
|
(if group-chat
|
||||||
|
(api/send-group-user-msg (assoc message :group-id chat-id))
|
||||||
|
(api/send-user-msg (assoc message :to chat-id)))))))))
|
|
@ -123,7 +123,7 @@
|
||||||
|
|
||||||
(defn actions-list-view [{styles :styles :as platform-specific}]
|
(defn actions-list-view [{styles :styles :as platform-specific}]
|
||||||
(let [{:keys [group-chat chat-id]} (subscribe [:chat-properties [:group-chat :chat-id]])
|
(let [{:keys [group-chat chat-id]} (subscribe [:chat-properties [:group-chat :chat-id]])
|
||||||
members (subscribe [:current-chat-contacts])
|
members (subscribe [:current-chat-contacts])
|
||||||
status-bar-height (get-in styles [:components :status-bar :default :height])]
|
status-bar-height (get-in styles [:components :status-bar :default :height])]
|
||||||
(when-let [actions (if @group-chat
|
(when-let [actions (if @group-chat
|
||||||
[{:title (label :t/members-title)
|
[{:title (label :t/members-title)
|
||||||
|
@ -203,9 +203,10 @@
|
||||||
(label :t/active-unknown))))
|
(label :t/active-unknown))))
|
||||||
|
|
||||||
(defn toolbar-content [platform-specific]
|
(defn toolbar-content [platform-specific]
|
||||||
(let [{:keys [group-chat chat-id name contacts]} (subscribe [:chat-properties [:group-chat :chat-id :name :contacts]])
|
(let [{:keys [group-chat name contacts chat-id]}
|
||||||
contact (subscribe [:get-in [:contacts @chat-id]])
|
(subscribe [:chat-properties [:group-chat :name :contacts :chat-id]])
|
||||||
show-actions (subscribe [:show-actions])]
|
show-actions (subscribe [:show-actions])
|
||||||
|
contact (subscribe [:get-in [:contacts @chat-id]])]
|
||||||
(fn []
|
(fn []
|
||||||
[view (st/chat-name-view @show-actions)
|
[view (st/chat-name-view @show-actions)
|
||||||
[text {:style st/chat-name-text
|
[text {:style st/chat-name-text
|
||||||
|
@ -242,7 +243,7 @@
|
||||||
|
|
||||||
(defn chat-toolbar [platform-specific]
|
(defn chat-toolbar [platform-specific]
|
||||||
(let [{:keys [group-chat name contacts]} (subscribe [:chat-properties [:group-chat :name :contacts]])
|
(let [{:keys [group-chat name contacts]} (subscribe [:chat-properties [:group-chat :name :contacts]])
|
||||||
show-actions (subscribe [:show-actions])]
|
show-actions (subscribe [:show-actions])]
|
||||||
[view
|
[view
|
||||||
[status-bar {:platform-specific platform-specific}]
|
[status-bar {:platform-specific platform-specific}]
|
||||||
[toolbar {:hide-nav? @show-actions
|
[toolbar {:hide-nav? @show-actions
|
||||||
|
@ -252,14 +253,15 @@
|
||||||
|
|
||||||
(defview messages-view [platform-specific group-chat]
|
(defview messages-view [platform-specific group-chat]
|
||||||
[messages [:chat :messages]
|
[messages [:chat :messages]
|
||||||
contacts [:chat :contacts]]
|
contacts [:chat :contacts]
|
||||||
|
loaded? [:all-messages-loaded?]]
|
||||||
(let [contacts' (contacts-by-identity contacts)]
|
(let [contacts' (contacts-by-identity contacts)]
|
||||||
[list-view {:renderRow (message-row {:contact-by-identity contacts'
|
[list-view {:renderRow (message-row {:contact-by-identity contacts'
|
||||||
:platform-specific platform-specific
|
:platform-specific platform-specific
|
||||||
:group-chat group-chat
|
:group-chat group-chat
|
||||||
:messages-count (count messages)})
|
:messages-count (count messages)})
|
||||||
:renderScrollComponent #(invertible-scroll-view (js->clj %))
|
:renderScrollComponent #(invertible-scroll-view (js->clj %))
|
||||||
:onEndReached #(dispatch [:load-more-messages])
|
:onEndReached (when-not loaded? #(dispatch [:load-more-messages]))
|
||||||
:enableEmptySections true
|
:enableEmptySections true
|
||||||
:keyboardShouldPersistTaps true
|
:keyboardShouldPersistTaps true
|
||||||
:dataSource (to-datasource-inverted messages)}]))
|
:dataSource (to-datasource-inverted messages)}]))
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
;; -- Send phone number ----------------------------------------
|
;; -- Send phone number ----------------------------------------
|
||||||
(defn on-sign-up-response [& [message]]
|
(defn on-sign-up-response [& [message]]
|
||||||
(let [msg-id (random/id)]
|
(let [msg-id (random/id)]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id msg-id
|
{:msg-id msg-id
|
||||||
:content (command-content
|
:content (command-content
|
||||||
:confirmation-code
|
:confirmation-code
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
;; -- Send confirmation code and synchronize contacts---------------------------
|
;; -- Send confirmation code and synchronize contacts---------------------------
|
||||||
(defn on-sync-contacts []
|
(defn on-sync-contacts []
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content (label :t/contacts-syncronized)
|
:content (label :t/contacts-syncronized)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
(dispatch [:sync-contacts on-sync-contacts]))
|
(dispatch [:sync-contacts on-sync-contacts]))
|
||||||
|
|
||||||
(defn on-send-code-response [body]
|
(defn on-send-code-response [body]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content (:message body)
|
:content (:message body)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
|
@ -96,47 +96,52 @@
|
||||||
;; -- Saving password ----------------------------------------
|
;; -- Saving password ----------------------------------------
|
||||||
(defn save-password [password]
|
(defn save-password [password]
|
||||||
;; TODO validate and save password
|
;; TODO validate and save password
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content (label :t/password-saved)
|
:content (label :t/password-saved)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"
|
||||||
(dispatch [:received-msg
|
:new? false}])
|
||||||
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content (label :t/generate-passphrase)
|
:content (label :t/generate-passphrase)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"
|
||||||
(dispatch [:received-msg
|
:new? false}])
|
||||||
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content (label :t/passphrase)
|
:content (label :t/passphrase)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"
|
||||||
|
:new? false}])
|
||||||
;; TODO generate passphrase
|
;; TODO generate passphrase
|
||||||
(let [passphrase (str "The brash businessman's braggadocio and public squabbing with "
|
(let [passphrase (str "The brash businessman's braggadocio and public squabbing with "
|
||||||
"candidates in the US presidential election")]
|
"candidates in the US presidential election")]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id (random/id)
|
{:msg-id (random/id)
|
||||||
:content passphrase
|
:content passphrase
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}]))
|
:to "me"
|
||||||
(dispatch [:received-msg
|
:new? false}]))
|
||||||
|
(dispatch [:received-message
|
||||||
{:msg-id "8"
|
{:msg-id "8"
|
||||||
:content (label :t/written-down)
|
:content (label :t/written-down)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"
|
||||||
|
:new? false}])
|
||||||
;; TODO highlight '!phone'
|
;; TODO highlight '!phone'
|
||||||
(let [msg-id (random/id)]
|
(let [msg-id (random/id)]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id msg-id
|
{:msg-id msg-id
|
||||||
:content (command-content
|
:content (command-content
|
||||||
:phone
|
:phone
|
||||||
|
@ -157,15 +162,15 @@
|
||||||
:to "me"})
|
:to "me"})
|
||||||
|
|
||||||
(defn intro [db]
|
(defn intro [db]
|
||||||
(dispatch [:received-msg intro-status])
|
(dispatch [:received-message intro-status])
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id "intro-message1"
|
{:msg-id "intro-message1"
|
||||||
:content (label :t/intro-message1)
|
:content (label :t/intro-message1)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:outgoing false
|
:outgoing false
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"}])
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id "intro-message2"
|
{:msg-id "intro-message2"
|
||||||
:content (label :t/intro-message2)
|
:content (label :t/intro-message2)
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
|
@ -173,7 +178,7 @@
|
||||||
:from "console"
|
:from "console"
|
||||||
:to "me"}])
|
:to "me"}])
|
||||||
(let [msg-id "into-message3"]
|
(let [msg-id "into-message3"]
|
||||||
(dispatch [:received-msg
|
(dispatch [:received-message
|
||||||
{:msg-id msg-id
|
{:msg-id msg-id
|
||||||
:content (command-content
|
:content (command-content
|
||||||
:keypair
|
:keypair
|
||||||
|
|
|
@ -3,15 +3,16 @@
|
||||||
[status-im.chat.constants :as constants]))
|
[status-im.chat.constants :as constants]))
|
||||||
|
|
||||||
(def messages-container
|
(def messages-container
|
||||||
{:background-color :red
|
{:background-color :#d50000
|
||||||
:height constants/request-info-height
|
:height constants/request-info-height
|
||||||
:padding-left 16
|
:padding-left 16
|
||||||
:padding-top 14})
|
:padding-top 12})
|
||||||
|
|
||||||
(def title
|
(def title
|
||||||
{:color :white
|
{:color :white
|
||||||
:font-size 12
|
:font-size 14
|
||||||
:font-family st/font})
|
:font-family st/font})
|
||||||
|
|
||||||
(def description
|
(def description
|
||||||
(assoc title :opacity 0.69))
|
(assoc title :opacity 0.9
|
||||||
|
:font-size 12))
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(->> [:chats (:current-chat-id @db) :staged-commands]
|
(->> [:chats (:current-chat-id @db) :staged-commands]
|
||||||
(get-in @db)
|
(get-in @db)
|
||||||
|
vals
|
||||||
(reaction))))
|
(reaction))))
|
||||||
|
|
||||||
(register-sub :valid-plain-message?
|
(register-sub :valid-plain-message?
|
||||||
|
@ -232,3 +233,8 @@
|
||||||
20
|
20
|
||||||
|
|
||||||
:else 0)))))
|
:else 0)))))
|
||||||
|
|
||||||
|
(register-sub :all-messages-loaded?
|
||||||
|
(fn [db]
|
||||||
|
(let [chat-id (subscribe [:get-current-chat-id])]
|
||||||
|
(reaction (get-in @db [:chats @chat-id :all-loaded?])))))
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
[status-im.db :as db]
|
[status-im.db :as db]
|
||||||
[status-im.models.commands :refer [get-commands
|
[status-im.models.commands :refer [get-commands
|
||||||
get-chat-command-request
|
get-chat-command-request
|
||||||
get-chat-command-to-msg-id
|
get-chat-command-to-msg-id]]
|
||||||
clear-staged-commands]]
|
|
||||||
[status-im.utils.utils :refer [log on-error http-get]]
|
[status-im.utils.utils :refer [log on-error http-get]]
|
||||||
[clojure.string :as s]))
|
[clojure.string :as s]))
|
||||||
|
|
||||||
|
@ -39,15 +38,6 @@
|
||||||
(fn []
|
(fn []
|
||||||
(command-handler to-msg-id command-key content)))))
|
(command-handler to-msg-id command-key content)))))
|
||||||
|
|
||||||
(defn apply-staged-commands [db]
|
|
||||||
(let [staged-commands (get-in db (db/chat-staged-commands-path
|
|
||||||
(:current-chat-id db)))]
|
|
||||||
(dorun (map (fn [staged-command]
|
|
||||||
(when-let [handler (:handler staged-command)]
|
|
||||||
(handler)))
|
|
||||||
staged-commands))
|
|
||||||
(clear-staged-commands db)))
|
|
||||||
|
|
||||||
(defn check-suggestion [db message]
|
(defn check-suggestion [db message]
|
||||||
(when-let [suggestion-text (when (string? message)
|
(when-let [suggestion-text (when (string? message)
|
||||||
(re-matches #"^![^\s]+\s" message))]
|
(re-matches #"^![^\s]+\s" message))]
|
||||||
|
@ -60,7 +50,3 @@
|
||||||
(-> db
|
(-> db
|
||||||
(get-in [:chats (:current-chat-id db) :input-text])
|
(get-in [:chats (:current-chat-id db) :input-text])
|
||||||
suggestion?))
|
suggestion?))
|
||||||
|
|
||||||
(defn switch-command-suggestions [db]
|
|
||||||
(let [text (if (typing-command? db) nil "!")]
|
|
||||||
(assoc-in db [:chats (:current-chat-id db) :input-text] text)))
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
(ns status-im.chat.utils)
|
||||||
|
|
||||||
|
(defn console? [s]
|
||||||
|
(= "console" s))
|
||||||
|
|
||||||
|
(def not-console?
|
||||||
|
(complement console?))
|
||||||
|
|
||||||
|
(defn add-message-to-db
|
||||||
|
([db chat-id message] (add-message-to-db db chat-id message true))
|
||||||
|
([db chat-id message new?]
|
||||||
|
(let [messages [:chats chat-id :messages]]
|
||||||
|
(update-in db messages conj (assoc message :chat-id chat-id
|
||||||
|
:new? (if (nil? new?)
|
||||||
|
true
|
||||||
|
new?))))))
|
||||||
|
|
||||||
|
(defn check-author-direction
|
||||||
|
[db chat-id {:keys [from outgoing] :as message}]
|
||||||
|
(let [previous-message (first (get-in db [:chats chat-id :messages]))]
|
||||||
|
(merge message
|
||||||
|
{:same-author (if previous-message
|
||||||
|
(= (:from previous-message) from)
|
||||||
|
true)
|
||||||
|
:same-direction (if previous-message
|
||||||
|
(= (:outgoing previous-message) outgoing)
|
||||||
|
true)})))
|
|
@ -88,7 +88,7 @@
|
||||||
[text {:style st/command-text
|
[text {:style st/command-text
|
||||||
:platform-specific platform-specific
|
:platform-specific platform-specific
|
||||||
:font :default}
|
:font :default}
|
||||||
content])]))
|
(str content)])]))
|
||||||
|
|
||||||
(defn set-chat-command [msg-id command]
|
(defn set-chat-command [msg-id command]
|
||||||
(dispatch [:set-response-chat-command msg-id (keyword (:name command))]))
|
(dispatch [:set-response-chat-command msg-id (keyword (:name command))]))
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
[text {:style (st/text-message message)
|
[text {:style (st/text-message message)
|
||||||
:platform-specific platform-specific
|
:platform-specific platform-specific
|
||||||
:font :default}
|
:font :default}
|
||||||
content]])
|
(str content)]])
|
||||||
|
|
||||||
(defmethod message-content text-content-type
|
(defmethod message-content text-content-type
|
||||||
[wrapper message platform-specific]
|
[wrapper message platform-specific]
|
||||||
|
@ -213,9 +213,7 @@
|
||||||
:callback anim-callback}
|
:callback anim-callback}
|
||||||
on-update (message-container-animation-logic context)]
|
on-update (message-container-animation-logic context)]
|
||||||
(r/create-class
|
(r/create-class
|
||||||
{:component-did-mount
|
{:component-did-update
|
||||||
on-update
|
|
||||||
:component-did-update
|
|
||||||
on-update
|
on-update
|
||||||
:reagent-render
|
:reagent-render
|
||||||
(fn [message & children]
|
(fn [message & children]
|
||||||
|
@ -241,7 +239,8 @@
|
||||||
(dispatch [:send-seen! chat-id msg-id])))
|
(dispatch [:send-seen! chat-id msg-id])))
|
||||||
:reagent-render
|
:reagent-render
|
||||||
(fn [{:keys [outgoing delivery-status timestamp new-day group-chat]
|
(fn [{:keys [outgoing delivery-status timestamp new-day group-chat]
|
||||||
:as message}]
|
:as message}
|
||||||
|
platform-specific]
|
||||||
[message-container message
|
[message-container message
|
||||||
;; TODO there is no new-day info in message
|
;; TODO there is no new-day info in message
|
||||||
(when new-day
|
(when new-day
|
||||||
|
|
|
@ -72,12 +72,14 @@
|
||||||
[suggestions [:get-suggestions]
|
[suggestions [:get-suggestions]
|
||||||
requests [:get-requests]]
|
requests [:get-requests]]
|
||||||
[scroll-view {:keyboardShouldPersistTaps true}
|
[scroll-view {:keyboardShouldPersistTaps true}
|
||||||
|
;; todo translations
|
||||||
(when (seq requests) [title "Requests"])
|
(when (seq requests) [title "Requests"])
|
||||||
(when (seq requests)
|
(when (seq requests)
|
||||||
[view
|
[view
|
||||||
[list-view {:dataSource (to-datasource requests)
|
[list-view {:dataSource (to-datasource requests)
|
||||||
:keyboardShouldPersistTaps true
|
:keyboardShouldPersistTaps true
|
||||||
:renderRow render-request-row}]])
|
:renderRow render-request-row}]])
|
||||||
|
;; todo translations
|
||||||
[title "Commands"]
|
[title "Commands"]
|
||||||
[view
|
[view
|
||||||
[list-view {:dataSource (to-datasource suggestions)
|
[list-view {:dataSource (to-datasource suggestions)
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
[{:keys [chat-id name color new-messages-count
|
[{:keys [chat-id name color new-messages-count
|
||||||
online group-chat contacts] :as chat}]
|
online group-chat contacts] :as chat}]
|
||||||
[unviewed-messages [:unviewed-messages-count chat-id]]
|
[unviewed-messages [:unviewed-messages-count chat-id]]
|
||||||
(let [last-message (first (:messages chat))]
|
(let [last-message (first (:messages chat))
|
||||||
|
name (or name chat-id)]
|
||||||
[view st/chat-container
|
[view st/chat-container
|
||||||
[view st/chat-icon-container
|
[view st/chat-icon-container
|
||||||
[chat-icon-view-chat-list chat-id group-chat name color online]]
|
[chat-icon-view-chat-list chat-id group-chat name color online]]
|
||||||
|
|
|
@ -19,24 +19,37 @@
|
||||||
(assoc-in db [:rendered-commands chat-id message-id] hiccup)))
|
(assoc-in db [:rendered-commands chat-id message-id] hiccup)))
|
||||||
|
|
||||||
(def console-events
|
(def console-events
|
||||||
{:save-password #(dispatch [:save-password %])
|
{:save-password (fn [[parameter]]
|
||||||
:sign-up #(dispatch [:sign-up %])
|
(dispatch [:save-password parameter]))
|
||||||
:confirm-sign-up #(dispatch [:sign-up-confirm %])})
|
:sign-up (fn [[parameter]]
|
||||||
|
(dispatch [:sign-up parameter]))
|
||||||
|
:confirm-sign-up (fn [[parameter]]
|
||||||
|
(dispatch [:sign-up-confirm parameter]))})
|
||||||
|
|
||||||
(def regular-events {})
|
(def regular-events {})
|
||||||
|
|
||||||
(defn command-hadler!
|
(defn command-hadler!
|
||||||
[_ [{:keys [to]} {:keys [result]} ]]
|
[_ [chat-id {:keys [command] :as parameters} {:keys [result error]}]]
|
||||||
(when result
|
(cond
|
||||||
(let [{:keys [event params]} result
|
result
|
||||||
events (if (= "console" to)
|
(let [{:keys [event params transaction-hash]} result
|
||||||
(merge regular-events console-events)
|
command' (assoc command :handler-data result)
|
||||||
regular-events)]
|
parameters' (assoc parameters :command command')]
|
||||||
(when-let [handler (events (keyword event))]
|
(if transaction-hash
|
||||||
(apply handler params)))))
|
(dispatch [:wait-for-transaction transaction-hash parameters'])
|
||||||
|
(let [events (if (= "console" chat-id)
|
||||||
|
(merge regular-events console-events)
|
||||||
|
regular-events)
|
||||||
|
parameters'' (if-let [handler (events (keyword event))]
|
||||||
|
(assoc parameters' :handler #(handler params command'))
|
||||||
|
parameters')]
|
||||||
|
(dispatch [:prepare-command! parameters'']))))
|
||||||
|
(not error)
|
||||||
|
(dispatch [:prepare-command! parameters])
|
||||||
|
:else nil))
|
||||||
|
|
||||||
(defn suggestions-handler!
|
(defn suggestions-handler!
|
||||||
[db [{:keys [chat-id]} {:keys [result]} ]]
|
[db [{:keys [chat-id]} {:keys [result]}]]
|
||||||
(let [{:keys [markup webViewUrl]} result
|
(let [{:keys [markup webViewUrl]} result
|
||||||
hiccup (generate-hiccup markup)]
|
hiccup (generate-hiccup markup)]
|
||||||
(-> db
|
(-> db
|
||||||
|
@ -52,13 +65,10 @@
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(defn command-preview
|
(defn command-preview
|
||||||
[db [chat-id {:keys [result]}]]
|
[db [chat-id command-id {:keys [result]}]]
|
||||||
(if result
|
(if result
|
||||||
(let [path [:chats chat-id :staged-commands]
|
(let [path [:chats chat-id :staged-commands command-id]]
|
||||||
commands-cnt (count (get-in db path))]
|
(update-in db path assoc
|
||||||
;; todo (dec commands-cnt) looks like hack have to find better way to
|
|
||||||
;; do this
|
|
||||||
(update-in db (conj path (dec commands-cnt)) assoc
|
|
||||||
:preview (generate-hiccup result)
|
:preview (generate-hiccup result)
|
||||||
:preview-string (str result)))
|
:preview-string (str result)))
|
||||||
db))
|
db))
|
||||||
|
@ -73,18 +83,20 @@
|
||||||
(reg-handler ::render-command render-command)
|
(reg-handler ::render-command render-command)
|
||||||
|
|
||||||
(reg-handler :command-handler!
|
(reg-handler :command-handler!
|
||||||
(after (print-error-message! "Error on command handling"))
|
(after (print-error-message! "Error on command handling"))
|
||||||
(u/side-effect! command-hadler!))
|
(u/side-effect! command-hadler!))
|
||||||
|
|
||||||
(reg-handler :suggestions-handler
|
(reg-handler :suggestions-handler
|
||||||
[(after #(dispatch [:animate-show-response]))
|
[(after #(dispatch [:animate-show-response]))
|
||||||
(after (print-error-message! "Error on param suggestions"))
|
(after (print-error-message! "Error on param suggestions"))
|
||||||
(after (fn [_ [{:keys [command]} {:keys [result]}]]
|
(after (fn [_ [{:keys [command]} {:keys [result]}]]
|
||||||
(when (= :on-send (keyword (:suggestions-trigger command)))
|
(when (= :on-send (keyword (:suggestions-trigger command)))
|
||||||
(when (:webViewUrl result)
|
(when (:webViewUrl result)
|
||||||
(dispatch [:set-soft-input-mode :pan]))
|
(dispatch [:set-soft-input-mode :pan]))
|
||||||
(r/dismiss-keyboard!))))]
|
(r/dismiss-keyboard!))))]
|
||||||
suggestions-handler!)
|
suggestions-handler!)
|
||||||
(reg-handler :suggestions-event! (u/side-effect! suggestions-events-handler!))
|
(reg-handler :suggestions-event! (u/side-effect! suggestions-events-handler!))
|
||||||
|
|
||||||
(reg-handler :command-preview
|
(reg-handler :command-preview
|
||||||
(after (print-error-message! "Error on command preview"))
|
(after (print-error-message! "Error on command preview"))
|
||||||
command-preview)
|
command-preview)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im.commands.handlers.loading
|
(ns status-im.commands.handlers.loading
|
||||||
(:require-macros [status-im.utils.slurp :refer [slurp]])
|
(:require-macros [status-im.utils.slurp :refer [slurp]])
|
||||||
(:require [re-frame.core :refer [after dispatch subscribe trim-v debug]]
|
(:require [re-frame.core :refer [path after dispatch subscribe trim-v debug]]
|
||||||
[status-im.utils.handlers :as u]
|
[status-im.utils.handlers :as u]
|
||||||
[status-im.utils.utils :refer [http-get toast]]
|
[status-im.utils.utils :refer [http-get toast]]
|
||||||
[clojure.string :as s]
|
[clojure.string :as s]
|
||||||
|
@ -22,10 +22,13 @@
|
||||||
|
|
||||||
(defn fetch-commands!
|
(defn fetch-commands!
|
||||||
[db [identity]]
|
[db [identity]]
|
||||||
(when-let [url (:dapp-url (get-in db [:chats identity]))]
|
(when true
|
||||||
(if (= "console" identity)
|
;;when-let [url (:dapp-url (get-in db [:chats identity]))]
|
||||||
|
;; todo fix this after demo
|
||||||
|
(if true
|
||||||
|
;(= "console" identity)
|
||||||
(dispatch [::validate-hash identity (slurp "resources/commands.js")])
|
(dispatch [::validate-hash identity (slurp "resources/commands.js")])
|
||||||
(http-get (s/join "/" [url commands-js])
|
#_(http-get (s/join "/" [url commands-js])
|
||||||
#(dispatch [::validate-hash identity %])
|
#(dispatch [::validate-hash identity %])
|
||||||
#(dispatch [::loading-failed! identity ::file-was-not-found])))))
|
#(dispatch [::loading-failed! identity ::file-was-not-found])))))
|
||||||
|
|
||||||
|
@ -68,8 +71,9 @@
|
||||||
(defn add-commands
|
(defn add-commands
|
||||||
[db [id _ {:keys [commands responses]}]]
|
[db [id _ {:keys [commands responses]}]]
|
||||||
(-> db
|
(-> db
|
||||||
(update-in [:chats id :commands] merge (mark-as :command commands))
|
(update-in [id :commands] merge (mark-as :command commands))
|
||||||
(update-in [:chats id :responses] merge (mark-as :response responses))))
|
(update-in [id :responses] merge (mark-as :response responses))
|
||||||
|
(assoc-in [id :commands-loaded] true)))
|
||||||
|
|
||||||
(defn save-commands-js!
|
(defn save-commands-js!
|
||||||
[_ [id file]]
|
[_ [id file]]
|
||||||
|
@ -96,7 +100,8 @@
|
||||||
(reg-handler ::parse-commands! (u/side-effect! parse-commands!))
|
(reg-handler ::parse-commands! (u/side-effect! parse-commands!))
|
||||||
|
|
||||||
(reg-handler ::add-commands
|
(reg-handler ::add-commands
|
||||||
(after save-commands-js!)
|
[(path :chats)
|
||||||
|
(after save-commands-js!)]
|
||||||
add-commands)
|
add-commands)
|
||||||
|
|
||||||
(reg-handler ::loading-failed! (u/side-effect! loading-failed!))
|
(reg-handler ::loading-failed! (u/side-effect! loading-failed!))
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
(defn get-active-page [data]
|
(defn get-active-page [data]
|
||||||
(get data :activePage 0))
|
(get data :activePage 0))
|
||||||
|
|
||||||
(defn get-sneak [data]
|
(defn get-sneak [{:keys [sneak count] }]
|
||||||
(get data :sneak (:sneak defaults)))
|
(if (> (or count 2) 1)
|
||||||
|
(or sneak (:sneak defaults))
|
||||||
|
0))
|
||||||
|
|
||||||
(defn get-gap [data]
|
(defn get-gap [data]
|
||||||
(get data :gap (:gap defaults)))
|
(get data :gap (:gap defaults)))
|
||||||
|
@ -64,7 +66,7 @@
|
||||||
state (reagent.core/state component)
|
state (reagent.core/state component)
|
||||||
page-width (get-page-width state)
|
page-width (get-page-width state)
|
||||||
gap (get-gap state)
|
gap (get-gap state)
|
||||||
page-position (* page (+ page-width gap))]
|
page-position (+ (* page page-width) (* (- page 1) gap))]
|
||||||
(log/debug "go-to-page: props-page-width=" page-width "; gap=" gap
|
(log/debug "go-to-page: props-page-width=" page-width "; gap=" gap
|
||||||
"; page-position=" page-position)
|
"; page-position=" page-position)
|
||||||
(scroll-to component page-position 0)
|
(scroll-to component page-position 0)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
{:flex 1})
|
{:flex 1})
|
||||||
|
|
||||||
(defn content-container [sneak gap]
|
(defn content-container [sneak gap]
|
||||||
{:paddingLeft (+ sneak (quot gap 2))
|
{:paddingLeft (+ 0 (quot gap 2))
|
||||||
:paddingRight (+ sneak (quot gap 2))})
|
:paddingRight (+ sneak (quot gap 2))})
|
||||||
|
|
||||||
(defn page [page-width margin]
|
(defn page [page-width margin]
|
||||||
|
|
|
@ -31,9 +31,9 @@
|
||||||
:style st/photo-pencil}]])]))
|
:style st/photo-pencil}]])]))
|
||||||
|
|
||||||
(defview chat-icon-view [chat-id group-chat name online styles]
|
(defview chat-icon-view [chat-id group-chat name online styles]
|
||||||
[photo-path [:chat-photo chat-id]]
|
[photo-path [:chat-photo chat-id]]
|
||||||
[view (:container styles)
|
[view (:container styles)
|
||||||
(if-not (s/blank? photo-path)
|
(if-not (or (s/blank? photo-path) (= chat-id "console"))
|
||||||
[chat-icon photo-path styles]
|
[chat-icon photo-path styles]
|
||||||
[default-chat-icon name styles])
|
[default-chat-icon name styles])
|
||||||
(when-not group-chat
|
(when-not group-chat
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
(ns status-im.components.geth
|
(ns status-im.components.geth
|
||||||
(:require [status-im.components.react :as r]))
|
(:require [status-im.components.react :as r]
|
||||||
|
[re-frame.core :refer [dispatch]]))
|
||||||
|
|
||||||
(def geth
|
(def geth
|
||||||
(when (exists? (.-NativeModules r/react-native))
|
(when (exists? (.-NativeModules r/react-native))
|
||||||
(.-Geth (.-NativeModules r/react-native))))
|
(.-Geth (.-NativeModules r/react-native))))
|
||||||
|
|
||||||
|
(defn register-signal-callback []
|
||||||
|
(when geth
|
||||||
|
(.registerSignalEventCallback
|
||||||
|
geth
|
||||||
|
#(do (dispatch [:signal-event %])
|
||||||
|
(register-signal-callback)))))
|
||||||
|
|
||||||
|
(register-signal-callback)
|
||||||
|
|
||||||
(defn start-node [on-result on-already-running]
|
(defn start-node [on-result on-already-running]
|
||||||
(when geth
|
(when geth
|
||||||
(.startNode geth on-result on-already-running)))
|
(.startNode geth on-result on-already-running)))
|
||||||
|
@ -15,4 +25,9 @@
|
||||||
|
|
||||||
(defn login [address password on-result]
|
(defn login [address password on-result]
|
||||||
(when geth
|
(when geth
|
||||||
(.login geth address password on-result)))
|
(.login geth address password on-result)))
|
||||||
|
|
||||||
|
(defn complete-transaction
|
||||||
|
[hash callback]
|
||||||
|
(when geth
|
||||||
|
(.completeTransaction geth hash callback)))
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
{:width 18
|
{:width 18
|
||||||
:height 18})
|
:height 18})
|
||||||
|
|
||||||
|
(def icon-close
|
||||||
|
{:width 12
|
||||||
|
:height 12})
|
||||||
|
|
||||||
(def form-text-input
|
(def form-text-input
|
||||||
{:marginLeft -4
|
{:marginLeft -4
|
||||||
:fontSize 14
|
:fontSize 14
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
:lineColor "#0000001f"
|
:lineColor "#0000001f"
|
||||||
:focusLineColor "#0000001f"
|
:focusLineColor "#0000001f"
|
||||||
:errorColor "#d50000"
|
:errorColor "#d50000"
|
||||||
|
:secureTextEntry false
|
||||||
:onFocus #()
|
:onFocus #()
|
||||||
:onBlur #()
|
:onBlur #()
|
||||||
:onChangeText #()
|
:onChangeText #()
|
||||||
|
@ -144,19 +145,19 @@
|
||||||
label-font-size
|
label-font-size
|
||||||
line-width
|
line-width
|
||||||
max-line-width] :as state} (r/state component)
|
max-line-width] :as state} (r/state component)
|
||||||
{:keys [wrapperStyle inputStyle lineColor focusLineColor
|
{:keys [wrapperStyle inputStyle lineColor focusLineColor secureTextEntry
|
||||||
labelColor errorColor error label value onFocus onBlur
|
labelColor errorColor error label value onFocus onBlur
|
||||||
onChangeText onChange editable] :as props} (merge default-props (r/props component))
|
onChangeText onChange editable] :as props} (merge default-props (r/props component))
|
||||||
lineColor (if error errorColor lineColor)
|
lineColor (if error errorColor lineColor)
|
||||||
focusLineColor (if error errorColor focusLineColor)
|
focusLineColor (if error errorColor focusLineColor)
|
||||||
labelColor (if (and error (not float-label?)) errorColor labelColor)
|
labelColor (if (and error (not float-label?)) errorColor labelColor)
|
||||||
label (if error (str label " *") label)]
|
label (if error (str label " *") label)]
|
||||||
;(log/debug "reagent-render: " data)
|
|
||||||
[view (merge st/text-field-container wrapperStyle)
|
[view (merge st/text-field-container wrapperStyle)
|
||||||
[animated-text {:style (st/label label-top label-font-size labelColor)} label]
|
[animated-text {:style (st/label label-top label-font-size labelColor)} label]
|
||||||
[text-input {:style (merge st/text-input inputStyle)
|
[text-input {:style (merge st/text-input inputStyle)
|
||||||
:placeholder ""
|
:placeholder ""
|
||||||
:editable editable
|
:editable editable
|
||||||
|
:secureTextEntry secureTextEntry
|
||||||
:onFocus #(on-focus {:component component
|
:onFocus #(on-focus {:component component
|
||||||
:animation {:top label-top
|
:animation {:top label-top
|
||||||
:to-top (:label-top config)
|
:to-top (:label-top config)
|
||||||
|
@ -192,4 +193,4 @@
|
||||||
:display-name "text-field"
|
:display-name "text-field"
|
||||||
:reagent-render reagent-render}]
|
:reagent-render reagent-render}]
|
||||||
;(log/debug "Creating text-field component: " data)
|
;(log/debug "Creating text-field component: " data)
|
||||||
(r/create-class component-data)))
|
(r/create-class component-data)))
|
||||||
|
|
|
@ -78,9 +78,10 @@
|
||||||
(into {})))
|
(into {})))
|
||||||
|
|
||||||
(defn add-identity [contacts-by-hash contacts]
|
(defn add-identity [contacts-by-hash contacts]
|
||||||
(map (fn [{:keys [phone-number-hash whisper-identity]}]
|
(map (fn [{:keys [phone-number-hash whisper-identity address]}]
|
||||||
(let [contact (contacts-by-hash phone-number-hash)]
|
(let [contact (contacts-by-hash phone-number-hash)]
|
||||||
(assoc contact :whisper-identity whisper-identity)))
|
(assoc contact :whisper-identity whisper-identity
|
||||||
|
:address address)))
|
||||||
(js->clj contacts)))
|
(js->clj contacts)))
|
||||||
|
|
||||||
(defn request-stored-contacts [contacts]
|
(defn request-stored-contacts [contacts]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contacts.subs
|
(ns status-im.contacts.subs
|
||||||
(:require-macros [reagent.ratom :refer [reaction]])
|
(:require-macros [reagent.ratom :refer [reaction]])
|
||||||
(:require [re-frame.core :refer [register-sub subscribe]]))
|
(:require [re-frame.core :refer [register-sub subscribe]]
|
||||||
|
[status-im.utils.identicon :refer [identicon]]))
|
||||||
|
|
||||||
(register-sub :get-contacts
|
(register-sub :get-contacts
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
|
@ -87,4 +88,6 @@
|
||||||
(if (:group-chat @chat)
|
(if (:group-chat @chat)
|
||||||
;; TODO return group chat icon
|
;; TODO return group chat icon
|
||||||
nil
|
nil
|
||||||
(:photo-path (first @contacts))))))))
|
(if (pos? (count @contacts))
|
||||||
|
(:photo-path (first @contacts))
|
||||||
|
(identicon chat-id))))))))
|
||||||
|
|
|
@ -41,11 +41,10 @@
|
||||||
:keyboard-height 0
|
:keyboard-height 0
|
||||||
:disable-group-creation false
|
:disable-group-creation false
|
||||||
:animations {;; todo clear this
|
:animations {;; todo clear this
|
||||||
:tabs-bar-value (anim/create-value 0)}})
|
:tabs-bar-value (anim/create-value 0)}
|
||||||
|
:loading-allowed true})
|
||||||
|
|
||||||
(def protocol-initialized-path [:protocol-initialized])
|
(def protocol-initialized-path [:protocol-initialized])
|
||||||
(defn chat-input-text-path [chat-id]
|
|
||||||
[:chats chat-id :input-text])
|
|
||||||
(defn chat-staged-commands-path [chat-id]
|
(defn chat-staged-commands-path [chat-id]
|
||||||
[:chats chat-id :staged-commands])
|
[:chats chat-id :staged-commands])
|
||||||
(defn chat-command-path [chat-id]
|
(defn chat-command-path [chat-id]
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
status-im.qr-scanner.handlers
|
status-im.qr-scanner.handlers
|
||||||
status-im.accounts.handlers
|
status-im.accounts.handlers
|
||||||
status-im.protocol.handlers
|
status-im.protocol.handlers
|
||||||
[status-im.utils.datetime :as time]))
|
[status-im.utils.datetime :as time]
|
||||||
|
status-im.transactions.handlers))
|
||||||
|
|
||||||
;; -- Middleware ------------------------------------------------------------
|
;; -- Middleware ------------------------------------------------------------
|
||||||
;;
|
;;
|
||||||
|
@ -103,7 +104,7 @@
|
||||||
(dispatch [:crypt-initialized]))))))))
|
(dispatch [:crypt-initialized]))))))))
|
||||||
|
|
||||||
(defn node-started [db result]
|
(defn node-started [db result]
|
||||||
(log/debug "Started Node: " result))
|
(log/debug "Started Node: "))
|
||||||
|
|
||||||
(register-handler :initialize-geth
|
(register-handler :initialize-geth
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
|
|
|
@ -101,11 +101,6 @@
|
||||||
(r/single-cljs)
|
(r/single-cljs)
|
||||||
(r/list-to-array :contacts)))
|
(r/list-to-array :contacts)))
|
||||||
|
|
||||||
(defn chat-by-id2 [chat-id]
|
|
||||||
(-> (r/get-by-field :account :chat :chat-id chat-id)
|
|
||||||
r/collection->map
|
|
||||||
first))
|
|
||||||
|
|
||||||
(defn chat-add-participants [chat-id identities]
|
(defn chat-add-participants [chat-id identities]
|
||||||
(r/write :account
|
(r/write :account
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.models.commands
|
(ns status-im.models.commands
|
||||||
(:require [status-im.db :as db]))
|
(:require [status-im.db :as db]
|
||||||
|
[tailrecursion.priority-map :refer [priority-map-by]]))
|
||||||
|
|
||||||
(defn get-commands [{:keys [current-chat-id] :as db}]
|
(defn get-commands [{:keys [current-chat-id] :as db}]
|
||||||
(or (get-in db [:chats current-chat-id :commands]) {}))
|
(or (get-in db [:chats current-chat-id :commands]) {}))
|
||||||
|
@ -37,21 +38,22 @@
|
||||||
[{:keys [current-chat-id] :as db}]
|
[{:keys [current-chat-id] :as db}]
|
||||||
(get-in db (db/chat-command-to-msg-id-path current-chat-id)))
|
(get-in db (db/chat-command-to-msg-id-path current-chat-id)))
|
||||||
|
|
||||||
|
(defn compare-commands
|
||||||
|
[{created-at-1 :created-at} {created-at-2 :created-at}]
|
||||||
|
(compare created-at-1 created-at-2))
|
||||||
|
|
||||||
(defn stage-command
|
(defn stage-command
|
||||||
[{:keys [current-chat-id] :as db} command-info]
|
[{:keys [current-chat-id] :as db} {:keys [id] :as command-info}]
|
||||||
(update-in db (db/chat-staged-commands-path current-chat-id)
|
(let [path (db/chat-staged-commands-path current-chat-id)
|
||||||
#(if %
|
staged-commands (get-in db path)
|
||||||
(conj % command-info)
|
staged-coomands' (if (seq staged-commands)
|
||||||
[command-info])))
|
staged-commands
|
||||||
|
(priority-map-by compare-commands))]
|
||||||
|
(assoc-in db path (assoc staged-coomands' id command-info))))
|
||||||
|
|
||||||
(defn unstage-command [db staged-command]
|
(defn unstage-command [db {:keys [id]}]
|
||||||
(update-in db (db/chat-staged-commands-path (:current-chat-id db))
|
(update-in db (db/chat-staged-commands-path (:current-chat-id db))
|
||||||
(fn [staged-commands]
|
dissoc id))
|
||||||
(filterv #(not= % staged-command) staged-commands))))
|
|
||||||
|
|
||||||
(defn clear-staged-commands
|
|
||||||
[{:keys [current-chat-id] :as db}]
|
|
||||||
(assoc-in db (db/chat-staged-commands-path current-chat-id) []))
|
|
||||||
|
|
||||||
(defn get-chat-command-request
|
(defn get-chat-command-request
|
||||||
[{:keys [current-chat-id] :as db}]
|
[{:keys [current-chat-id] :as db}]
|
||||||
|
|
|
@ -57,9 +57,13 @@
|
||||||
(r/collection->map))
|
(r/collection->map))
|
||||||
(into '())
|
(into '())
|
||||||
reverse
|
reverse
|
||||||
(keep (fn [{:keys [content-type] :as message}]
|
(keep (fn [{:keys [content-type preview] :as message}]
|
||||||
(if (command-type? content-type)
|
(if (command-type? content-type)
|
||||||
(update message :content str-to-map)
|
(-> message
|
||||||
|
(update :content str-to-map)
|
||||||
|
(assoc :rendered-preview
|
||||||
|
(when preview
|
||||||
|
(generate-hiccup (read-string preview)))))
|
||||||
message))))))
|
message))))))
|
||||||
|
|
||||||
(defn update-message! [{:keys [msg-id] :as msg}]
|
(defn update-message! [{:keys [msg-id] :as msg}]
|
||||||
|
@ -68,3 +72,7 @@
|
||||||
(fn []
|
(fn []
|
||||||
(when (r/exists? :account :message :msg-id msg-id)
|
(when (r/exists? :account :message :msg-id msg-id)
|
||||||
(r/create :account :message msg true)))))
|
(r/create :account :message msg true)))))
|
||||||
|
|
||||||
|
(defn get-message [id]
|
||||||
|
(r/get-one-by-field :account :message :msg-id id))
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,10 @@
|
||||||
|
|
||||||
(register-handler :navigate-to
|
(register-handler :navigate-to
|
||||||
(enrich preload-data!)
|
(enrich preload-data!)
|
||||||
(fn [db [_ view-id]]
|
(fn [{:keys [view-id] :as db} [_ new-view-id]]
|
||||||
(push-view db view-id)))
|
(if (= view-id new-view-id)
|
||||||
|
db
|
||||||
|
(push-view db new-view-id))))
|
||||||
|
|
||||||
(register-handler :navigation-replace
|
(register-handler :navigation-replace
|
||||||
(enrich preload-data!)
|
(enrich preload-data!)
|
||||||
|
|
|
@ -128,3 +128,8 @@
|
||||||
(after (fn [_ [_ chat-id]]
|
(after (fn [_ [_ chat-id]]
|
||||||
(dispatch [:remove-unviewed-messages chat-id])))]
|
(dispatch [:remove-unviewed-messages chat-id])))]
|
||||||
(update-message-status :seen))
|
(update-message-status :seen))
|
||||||
|
|
||||||
|
(register-handler :send-transaction!
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ amount message]]
|
||||||
|
(println :send-transacion! amount message))))
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
:active-group-ids (active-group-chats)
|
:active-group-ids (active-group-chats)
|
||||||
:storage kv/kv-store
|
:storage kv/kv-store
|
||||||
:handler (fn [{:keys [event-type] :as event}]
|
:handler (fn [{:keys [event-type] :as event}]
|
||||||
(log/info "Event:" (clj->js event))
|
|
||||||
(case event-type
|
(case event-type
|
||||||
:initialized (let [{:keys [identity]} event]
|
:initialized (let [{:keys [identity]} event]
|
||||||
(dispatch [:protocol-initialized identity]))
|
(dispatch [:protocol-initialized identity]))
|
||||||
:new-msg (let [{:keys [from to payload]} event]
|
:new-msg (let [{:keys [from to payload]} event]
|
||||||
(dispatch [:received-msg (assoc payload :from from :to to)]))
|
(dispatch [:received-message (assoc payload :from from :to to)]))
|
||||||
:msg-acked (let [{:keys [msg-id from]} event]
|
:msg-acked (let [{:keys [msg-id from]} event]
|
||||||
(dispatch [:acked-msg from msg-id]))
|
(dispatch [:acked-msg from msg-id]))
|
||||||
:msg-seen (let [{:keys [msg-id from]} event]
|
:msg-seen (let [{:keys [msg-id from]} event]
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
status-im.discovery.subs
|
status-im.discovery.subs
|
||||||
status-im.contacts.subs
|
status-im.contacts.subs
|
||||||
status-im.new-group.subs
|
status-im.new-group.subs
|
||||||
status-im.participants.subs))
|
status-im.participants.subs
|
||||||
|
status-im.transactions.subs))
|
||||||
|
|
||||||
(register-sub :get
|
(register-sub :get
|
||||||
(fn [db [_ k]]
|
(fn [db [_ k]]
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
(ns status-im.transactions.handlers
|
||||||
|
(:require [re-frame.core :refer [after dispatch debug enrich]]
|
||||||
|
[status-im.utils.handlers :refer [register-handler]]
|
||||||
|
[status-im.navigation.handlers :as nav]
|
||||||
|
[status-im.utils.handlers :as u]
|
||||||
|
[status-im.utils.types :as t]
|
||||||
|
[status-im.components.geth :as g]
|
||||||
|
cljsjs.web3
|
||||||
|
[clojure.string :as s]))
|
||||||
|
|
||||||
|
(defmethod nav/preload-data! :confirm
|
||||||
|
[{:keys [transactions-queue] :as db} _]
|
||||||
|
(assoc db :transactions transactions-queue))
|
||||||
|
|
||||||
|
(defn on-unlock [hashes]
|
||||||
|
(fn [result-str]
|
||||||
|
(let [{:keys [error]} (t/json->clj result-str)]
|
||||||
|
;; todo: add message about wrong password
|
||||||
|
(if (s/blank? error)
|
||||||
|
(do
|
||||||
|
(dispatch [:set :wrong-password? false])
|
||||||
|
(doseq [hash hashes]
|
||||||
|
(g/complete-transaction
|
||||||
|
hash
|
||||||
|
#(dispatch [:transaction-completed hash %])))
|
||||||
|
(dispatch [:navigate-back]))
|
||||||
|
(dispatch [:set :wrong-password? true])))))
|
||||||
|
|
||||||
|
(register-handler :accept-transactions
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [transactions current-account-id]} [_ password]]
|
||||||
|
(let [hashes (keys transactions)]
|
||||||
|
(g/login current-account-id password (on-unlock hashes))))))
|
||||||
|
|
||||||
|
(register-handler :deny-transactions
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [transactions]}]
|
||||||
|
(let [hashes (keys transactions)]
|
||||||
|
(dispatch [::remove-pending-messages hashes])
|
||||||
|
(dispatch [::remove-trqqansactions hashes])
|
||||||
|
(dispatch [:navigate-back])))))
|
||||||
|
|
||||||
|
(register-handler :deny-transaction
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ hash]]
|
||||||
|
(dispatch [::remove-pending-message hash])
|
||||||
|
(dispatch [::remove-transaction hash]))))
|
||||||
|
|
||||||
|
(register-handler ::remove-transactions
|
||||||
|
(fn [db [_ hashes]]
|
||||||
|
(-> db
|
||||||
|
(dissoc :transactions)
|
||||||
|
(update :transactions-queue #(apply dissoc % hashes)))))
|
||||||
|
|
||||||
|
(register-handler ::remove-transaction
|
||||||
|
(fn [db [_ hash]]
|
||||||
|
(-> db
|
||||||
|
(update :transactions dissoc hash)
|
||||||
|
(update :transactions-queue dissoc hash))))
|
||||||
|
|
||||||
|
(register-handler :wait-for-transaction
|
||||||
|
(fn [db [_ hash {:keys [chat-id command] :as params}]]
|
||||||
|
(let [id (:id command)]
|
||||||
|
(-> db
|
||||||
|
(update-in [:chats chat-id :staged-commands id] assoc :pending true)
|
||||||
|
(assoc-in [:transaction-subscribers hash] params)))))
|
||||||
|
|
||||||
|
(defn remove-pending-message [db hash]
|
||||||
|
(let [{:keys [chat-id command]} (get-in db [:transaction-subscribers hash])
|
||||||
|
path [:chats chat-id :staged-commands]]
|
||||||
|
(-> db
|
||||||
|
(update :transaction-subscribers dissoc hash)
|
||||||
|
(update-in path dissoc (:id command)))))
|
||||||
|
|
||||||
|
(register-handler ::remove-pending-messages
|
||||||
|
(fn [db [_ hashes]]
|
||||||
|
(reduce remove-pending-message db hashes)))
|
||||||
|
|
||||||
|
(register-handler ::remove-pending-message
|
||||||
|
(fn [db [_ hash]]
|
||||||
|
(remove-pending-message db hash)))
|
||||||
|
|
||||||
|
(register-handler :signal-event
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ event-str]]
|
||||||
|
(let [{:keys [type event]} (t/json->clj event-str)]
|
||||||
|
(case type
|
||||||
|
"sendTransactionQueued" (dispatch [:transaction-queued event]))))))
|
||||||
|
|
||||||
|
(register-handler :transaction-queued
|
||||||
|
(after #(dispatch [:navigate-to :confirm]))
|
||||||
|
(fn [db [_ {:keys [hash args]}]]
|
||||||
|
(let [{:keys [from to value]} args
|
||||||
|
transaction {:hash hash
|
||||||
|
:from from
|
||||||
|
:to to
|
||||||
|
:value (.toDecimal js/Web3.prototype value)}]
|
||||||
|
(assoc-in db [:transactions-queue hash] transaction))))
|
||||||
|
|
||||||
|
(register-handler :transaction-completed
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [db [_ old-hash result-str]]
|
||||||
|
(let [{:keys [hash error]} (t/json->clj result-str)]
|
||||||
|
;; todo: handle error
|
||||||
|
(when hash
|
||||||
|
(dispatch [::send-pending-message old-hash hash])
|
||||||
|
(dispatch [::remove-transaction old-hash]))))))
|
||||||
|
|
||||||
|
(register-handler ::send-pending-message
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [transaction-subscribers] :as db} [_ old-hash new-hash]]
|
||||||
|
(when-let [params (transaction-subscribers old-hash)]
|
||||||
|
(let [params' (assoc-in params [:handler-data :transaction-hash] new-hash)]
|
||||||
|
(dispatch [:prepare-command! params']))
|
||||||
|
(dispatch [::remove-transaction-subscriber old-hash])))))
|
||||||
|
|
||||||
|
(register-handler ::remove-transaction-subscriber
|
||||||
|
(fn [db [_ old-hash]]
|
||||||
|
(update db :transaction-subscribers dissoc old-hash)))
|
|
@ -0,0 +1,62 @@
|
||||||
|
(ns status-im.transactions.screen
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview]])
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
text
|
||||||
|
image
|
||||||
|
icon
|
||||||
|
scroll-view
|
||||||
|
touchable-highlight
|
||||||
|
touchable-opacity]]
|
||||||
|
[status-im.components.styles :refer [icon-ok
|
||||||
|
icon-close
|
||||||
|
toolbar-title-container]]
|
||||||
|
[status-im.components.carousel.carousel :refer [carousel]]
|
||||||
|
[status-im.components.toolbar :refer [toolbar]]
|
||||||
|
[status-im.components.text-field.view :refer [text-field]]
|
||||||
|
[status-im.transactions.views.transaction-page :refer [transaction-page]]
|
||||||
|
[status-im.transactions.styles :as st]
|
||||||
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
|
[clojure.string :as s]))
|
||||||
|
|
||||||
|
|
||||||
|
(defview confirm []
|
||||||
|
[transactions [:transactions]
|
||||||
|
{:keys [password]} [:get :confirm-transactions]
|
||||||
|
wrong-password? [:wrong-password?]]
|
||||||
|
[view st/transactions-screen
|
||||||
|
[toolbar
|
||||||
|
{:style st/transactions-toolbar
|
||||||
|
:nav-action {:image {:source {:uri :icon_close_white}
|
||||||
|
:style icon-close}
|
||||||
|
:handler #(dispatch [:deny-transactions])}
|
||||||
|
:custom-content [view {:style toolbar-title-container}
|
||||||
|
[text {:style st/toolbar-title-text}
|
||||||
|
(label-pluralize (count transactions) :t/confirm-transactions)]]
|
||||||
|
:action {:image {:source {:uri (if-not (s/blank? password)
|
||||||
|
:icon_ok
|
||||||
|
:icon_ok_disabled_inversed)}
|
||||||
|
:style icon-ok}
|
||||||
|
:handler #(dispatch [:accept-transactions password])}}]
|
||||||
|
[view st/carousel-container
|
||||||
|
[carousel {:pageStyle st/carousel-page-style
|
||||||
|
:gap 16
|
||||||
|
:count (count transactions)
|
||||||
|
:sneak 20}
|
||||||
|
(when transactions
|
||||||
|
(for [transaction transactions]
|
||||||
|
[transaction-page transaction]))]]
|
||||||
|
[view st/form-container
|
||||||
|
[text-field
|
||||||
|
{:inputStyle st/password-style
|
||||||
|
:secureTextEntry true
|
||||||
|
:error (when wrong-password? (label :t/wrong-password))
|
||||||
|
:errorColor :#ffffff80 #_:#7099e6
|
||||||
|
:lineColor :white
|
||||||
|
:labelColor :#ffffff80
|
||||||
|
:value password
|
||||||
|
:label (label :t/password)
|
||||||
|
:onChangeText #(dispatch [:set-in [:confirm-transactions :password] %])}]]])
|
||||||
|
|
||||||
|
|
||||||
|
;(re-frame.core/dispatch [:set :view-id :confirm])
|
|
@ -0,0 +1,107 @@
|
||||||
|
(ns status-im.transactions.styles
|
||||||
|
(:require [status-im.components.styles :refer [toolbar-height
|
||||||
|
color-white]]))
|
||||||
|
|
||||||
|
|
||||||
|
(def transactions-screen
|
||||||
|
{:flex 1
|
||||||
|
:backgroundColor "#828b92"})
|
||||||
|
|
||||||
|
(def transactions-toolbar
|
||||||
|
{:backgroundColor "#828b92"
|
||||||
|
:elevation 0})
|
||||||
|
|
||||||
|
(def toolbar-title-text
|
||||||
|
{:color :white
|
||||||
|
:fontSize 16})
|
||||||
|
|
||||||
|
(def carousel-page-style
|
||||||
|
{})
|
||||||
|
|
||||||
|
(def form-container
|
||||||
|
{:flex 1
|
||||||
|
:paddingLeft 16})
|
||||||
|
|
||||||
|
(def password-style
|
||||||
|
{:color :white})
|
||||||
|
|
||||||
|
;transaction-page
|
||||||
|
|
||||||
|
(def transaction-page
|
||||||
|
{:flex 1
|
||||||
|
:backgroundColor "#f3f4f4"})
|
||||||
|
|
||||||
|
(def title-bar
|
||||||
|
{:backgroundColor :white
|
||||||
|
:height 39
|
||||||
|
:justifyContent :center})
|
||||||
|
|
||||||
|
(def title-bar-text
|
||||||
|
{:fontFamily "sans-serif-medium"
|
||||||
|
:color "#838c93"
|
||||||
|
:fontSize 13
|
||||||
|
:marginLeft 12})
|
||||||
|
|
||||||
|
(def icon-close-container
|
||||||
|
{:position :absolute
|
||||||
|
:right 12
|
||||||
|
:top 13})
|
||||||
|
|
||||||
|
(def icon-close
|
||||||
|
{:width 12
|
||||||
|
:height 12})
|
||||||
|
|
||||||
|
(def transaction-info-container
|
||||||
|
{:flex 1
|
||||||
|
:paddingTop 6})
|
||||||
|
|
||||||
|
(def scroll-view-container
|
||||||
|
{:flex 1})
|
||||||
|
|
||||||
|
(def scroll-view
|
||||||
|
{:flex 1
|
||||||
|
:height 175})
|
||||||
|
|
||||||
|
(def scroll-view-content
|
||||||
|
{:paddingVertical 6})
|
||||||
|
|
||||||
|
(def transaction-info-row
|
||||||
|
{:flex 1
|
||||||
|
:flexDirection :row
|
||||||
|
:height 20
|
||||||
|
})
|
||||||
|
|
||||||
|
(def transaction-info-column-title
|
||||||
|
{:flex 0.4
|
||||||
|
:flexDirection :column
|
||||||
|
:paddingHorizontal 6})
|
||||||
|
|
||||||
|
(def transaction-info-column-value
|
||||||
|
{:flex 0.6
|
||||||
|
:flexDirection :column
|
||||||
|
:paddingHorizontal 6})
|
||||||
|
|
||||||
|
(def transaction-info-item
|
||||||
|
{:flex 1
|
||||||
|
:padding 6})
|
||||||
|
|
||||||
|
(def transaction-info-title
|
||||||
|
{:textAlign :right
|
||||||
|
:color "#838c93de"
|
||||||
|
:fontSize 14
|
||||||
|
:lineHeight 20})
|
||||||
|
|
||||||
|
(def transaction-info-value
|
||||||
|
{:color "#000000de"
|
||||||
|
:fontSize 14
|
||||||
|
:lineHeight 20
|
||||||
|
})
|
||||||
|
|
||||||
|
(def scroll-view-item
|
||||||
|
{:flex 1
|
||||||
|
:height 20
|
||||||
|
:padding 6 })
|
||||||
|
|
||||||
|
(def carousel-container
|
||||||
|
{:min-height 215
|
||||||
|
:flex 1})
|
|
@ -0,0 +1,28 @@
|
||||||
|
(ns status-im.transactions.subs
|
||||||
|
(:require-macros [reagent.ratom :refer [reaction]])
|
||||||
|
(:require [re-frame.core :refer [register-sub subscribe]]
|
||||||
|
[clojure.string :as s]))
|
||||||
|
|
||||||
|
(register-sub :transactions
|
||||||
|
(fn [db]
|
||||||
|
(reaction (vals (:transactions @db)))))
|
||||||
|
|
||||||
|
(register-sub :contacts-by-address
|
||||||
|
(fn [db]
|
||||||
|
(reaction (into {} (map (fn [[_ {:keys [address] :as contact}]]
|
||||||
|
[address contact])
|
||||||
|
|
||||||
|
(:contacts @db)
|
||||||
|
)))))
|
||||||
|
|
||||||
|
(register-sub :contact-by-address
|
||||||
|
(fn [_ [_ address]]
|
||||||
|
(let [contacts (subscribe [:contacts-by-address])
|
||||||
|
address' (when address
|
||||||
|
(if (s/starts-with? address "0x")
|
||||||
|
(subs address 2)
|
||||||
|
address))]
|
||||||
|
(reaction (@contacts address')))))
|
||||||
|
|
||||||
|
(register-sub :wrong-password?
|
||||||
|
(fn [db] (reaction (:wrong-password? @db))))
|
|
@ -0,0 +1,49 @@
|
||||||
|
(ns status-im.transactions.views.transaction-page
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview]])
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
text
|
||||||
|
image
|
||||||
|
icon
|
||||||
|
scroll-view
|
||||||
|
touchable-highlight
|
||||||
|
touchable-opacity]]
|
||||||
|
[status-im.components.styles :refer [icon-ok
|
||||||
|
icon-close]]
|
||||||
|
[status-im.transactions.styles :as st]
|
||||||
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
|
cljsjs.web3))
|
||||||
|
|
||||||
|
(defn title-bar [title hash]
|
||||||
|
[view st/title-bar
|
||||||
|
[text {:style st/title-bar-text} title]
|
||||||
|
[touchable-highlight {:style st/icon-close-container
|
||||||
|
:on-press #(dispatch [:deny-transaction hash])}
|
||||||
|
[view [image {:source {:uri :icon_close_gray}
|
||||||
|
:style st/icon-close}]]]])
|
||||||
|
|
||||||
|
(defn transaction-info [index [name value]]
|
||||||
|
[view {:style st/transaction-info-item
|
||||||
|
:key index}
|
||||||
|
[view {:style st/transaction-info-row}
|
||||||
|
[view st/transaction-info-column-title
|
||||||
|
[text {:style st/transaction-info-title} name]]
|
||||||
|
[view st/transaction-info-column-value
|
||||||
|
[text {:style st/transaction-info-value} value]]]])
|
||||||
|
|
||||||
|
(defview transaction-page [{:keys [hash from to value] :as transaction}]
|
||||||
|
[{:keys [name] :as contact} [:contact-by-address to]]
|
||||||
|
(let [eth-value (.fromWei js/Web3.prototype value "ether")
|
||||||
|
title (str eth-value " ETH to " name)
|
||||||
|
transactions-info [[(label :t/status) (label :t/pending-confirmation)]
|
||||||
|
[(label :t/recipient) name]
|
||||||
|
[(label :t/value) (str eth-value " ETH")]]]
|
||||||
|
[view {:style st/transaction-page
|
||||||
|
:key hash}
|
||||||
|
[title-bar title hash]
|
||||||
|
[view st/scroll-view-container
|
||||||
|
[scroll-view {:style st/scroll-view
|
||||||
|
:contentContainerStyle st/scroll-view-content
|
||||||
|
:showsVerticalScrollIndicator true
|
||||||
|
:scrollEnabled true}
|
||||||
|
(map-indexed transaction-info transactions-info)]]]))
|
|
@ -160,9 +160,22 @@
|
||||||
:login "Login"
|
:login "Login"
|
||||||
:wrong-password "Wrong password"
|
:wrong-password "Wrong password"
|
||||||
|
|
||||||
;users
|
;accounts
|
||||||
:add-account "Add account"
|
:add-account "Add account"
|
||||||
|
|
||||||
;validation
|
;validation
|
||||||
:invalid-phone "Invalid phone number"
|
:invalid-phone "Invalid phone number"
|
||||||
|
:amount "Amount"
|
||||||
|
:not-enough-eth (str "Not enough ETH on balance "
|
||||||
|
"({{balance}} ETH)")
|
||||||
|
;transactions
|
||||||
|
:confirm-transactions {:one "Confirm transaction"
|
||||||
|
:other "Confirm {{count}} transactions"
|
||||||
|
:zero "No transactions"}
|
||||||
|
:status "Status"
|
||||||
|
:pending-confirmation "Pending confirmation"
|
||||||
|
:recipient "Recipient"
|
||||||
|
:one-more-item "One more item"
|
||||||
|
:fee "Fee"
|
||||||
|
:value "Value"
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,15 +4,17 @@
|
||||||
[cljs-time.format :refer [formatters
|
[cljs-time.format :refer [formatters
|
||||||
formatter
|
formatter
|
||||||
unparse]]
|
unparse]]
|
||||||
[status-im.i18n :refer [label label-pluralize]]))
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
|
[goog.string :as gstring]
|
||||||
|
goog.string.format))
|
||||||
|
|
||||||
(def hour (* 1000 60 60))
|
(def hour (* 1000 60 60))
|
||||||
(def day (* hour 24))
|
(def day (* hour 24))
|
||||||
(def week (* 7 day))
|
(def week (* 7 day))
|
||||||
(def units [{:name (label :t/datetime-second) :limit 60 :in-second 1}
|
(def units [{:name :t/datetime-second :limit 60 :in-second 1}
|
||||||
{:name (label :t/datetime-minute) :limit 3600 :in-second 60}
|
{:name :t/datetime-minute :limit 3600 :in-second 60}
|
||||||
{:name (label :t/datetime-hour) :limit 86400 :in-second 3600}
|
{:name :t/datetime-hour :limit 86400 :in-second 3600}
|
||||||
{:name (label :t/datetime-day) :limit nil :in-second 86400}])
|
{:name :t/datetime-day :limit nil :in-second 86400}])
|
||||||
|
|
||||||
(def time-zone-offset (hours (- (/ (.getTimezoneOffset (js/Date.)) 60))))
|
(def time-zone-offset (hours (- (/ (.getTimezoneOffset (js/Date.)) 60))))
|
||||||
|
|
||||||
|
@ -29,6 +31,10 @@
|
||||||
(before? local today) (label :t/datetime-yesterday)
|
(before? local today) (label :t/datetime-yesterday)
|
||||||
:else (unparse (formatters :hour-minute) local))))
|
:else (unparse (formatters :hour-minute) local))))
|
||||||
|
|
||||||
|
(defn format-time-ago [diff unit]
|
||||||
|
(let [name (label-pluralize diff (:name unit))]
|
||||||
|
(gstring/format "%s %s %s" diff name (label :t/datetime-ago))))
|
||||||
|
|
||||||
(defn time-ago [time]
|
(defn time-ago [time]
|
||||||
(let [diff (t/in-seconds (t/interval time (t/now)))]
|
(let [diff (t/in-seconds (t/interval time (t/now)))]
|
||||||
(if (< diff 60)
|
(if (< diff 60)
|
||||||
|
@ -39,7 +45,7 @@
|
||||||
(-> (/ diff (:in-second unit))
|
(-> (/ diff (:in-second unit))
|
||||||
Math/floor
|
Math/floor
|
||||||
int
|
int
|
||||||
(#(str % " " (label-pluralize % (:name unit)) " " (label :t/datetime-ago))))))))
|
(format-time-ago unit))))))
|
||||||
|
|
||||||
(defn to-date [ms]
|
(defn to-date [ms]
|
||||||
(from-long ms))
|
(from-long ms))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.utils.handlers
|
(ns status-im.utils.handlers
|
||||||
(:require [re-frame.core :refer [after dispatch debug] :as re-core]))
|
(:require [re-frame.core :refer [after dispatch debug] :as re-core]
|
||||||
|
[re-frame.utils :refer [log]]))
|
||||||
|
|
||||||
(defn side-effect!
|
(defn side-effect!
|
||||||
"Middleware for handlers that will not affect db."
|
"Middleware for handlers that will not affect db."
|
||||||
|
@ -8,7 +9,18 @@
|
||||||
(handler db params)
|
(handler db params)
|
||||||
db))
|
db))
|
||||||
|
|
||||||
|
(defn debug-handlers-names
|
||||||
|
"Middleware which logs debug information to js/console for each event.
|
||||||
|
Includes a clojure.data/diff of the db, before vs after, showing the changes
|
||||||
|
caused by the event."
|
||||||
|
[handler]
|
||||||
|
(fn debug-handler
|
||||||
|
[db v]
|
||||||
|
(log "Handling re-frame event: " (first v))
|
||||||
|
(let [new-db (handler db v)]
|
||||||
|
new-db)))
|
||||||
|
|
||||||
(defn register-handler
|
(defn register-handler
|
||||||
([name handler] (register-handler name nil handler))
|
([name handler] (register-handler name nil handler))
|
||||||
([name middleware handler]
|
([name middleware handler]
|
||||||
(re-core/register-handler name [#_debug middleware] handler)))
|
(re-core/register-handler name [debug-handlers-names middleware] handler)))
|
||||||
|
|
Loading…
Reference in New Issue