Merge pull request #128 from status-im/feature/#123
Fetch/store commands.js
Former-commit-id: d00e6405c4
This commit is contained in:
commit
2daf477954
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "StatusIm",
|
||||
"interface": "reagent",
|
||||
"androidHost": "localhost",
|
||||
"androidHost": "10.0.3.2",
|
||||
"modules": [
|
||||
"react-native-contacts",
|
||||
"react-native-invertible-scroll-view",
|
||||
|
@ -17,6 +17,7 @@
|
|||
"dismissKeyboard",
|
||||
"react-native-linear-gradient",
|
||||
"react-native-android-sms-listener",
|
||||
"react-native-status",
|
||||
"react-native-camera",
|
||||
"react-native-qrcode",
|
||||
"react-native-orientation",
|
||||
|
|
|
@ -131,9 +131,9 @@ dependencies {
|
|||
compile project(':react-native-linear-gradient')
|
||||
compile project(':ReactNativeAndroidSmsListener')
|
||||
compile project(':react-native-camera')
|
||||
compile project(':react-native-status')
|
||||
compile project(':react-native-orientation')
|
||||
// compile(name:'geth', ext:'aar')
|
||||
compile(group: 'status-im', name: 'android-geth', version: '1.4.0-201604110816-a97a114', ext: 'aar')
|
||||
compile(group: 'status-im', name: 'status-go', version: '0.1.0-201606231357-85abe1', ext: 'aar')
|
||||
|
||||
compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"])
|
||||
}
|
||||
|
@ -143,3 +143,4 @@ task copyDownloadableDepsToLibs(type: Copy) {
|
|||
from configurations.compile
|
||||
into 'libs'
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Intent;
|
|||
import android.os.Handler;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.annotation.Nullable;
|
||||
|
@ -14,7 +13,7 @@ import android.os.Environment;
|
|||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import com.github.ethereum.go_ethereum.cmd.Geth;
|
||||
import com.github.status_im.status_go.Statusgo;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
@ -78,20 +77,11 @@ public class GethService extends Service {
|
|||
extStore.getAbsolutePath() :
|
||||
getApplicationInfo().dataDir;
|
||||
|
||||
final Runnable addPeer = new Runnable() {
|
||||
public void run() {
|
||||
Log.w("Geth", "adding peer");
|
||||
Geth.run("--exec admin.addPeer(\"enode://e2f28126720452aa82f7d3083e49e6b3945502cb94d9750a15e27ee310eed6991618199f878e5fbc7dfa0e20f0af9554b41f491dc8f1dbae8f0f2d37a3a613aa@139.162.13.89:55555\") attach http://localhost:8545");
|
||||
}
|
||||
};
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
Geth.run("--shh --ipcdisable --nodiscover --rpc --rpcapi db,eth,net,web3,shh,admin --fast --datadir=" + dataFolder);
|
||||
Statusgo.doStartNode(dataFolder);
|
||||
}
|
||||
}).start();
|
||||
|
||||
handler.postDelayed(addPeer, 5000);
|
||||
}
|
||||
|
||||
public void signalEvent(String jsonEvent) {
|
||||
|
@ -107,8 +97,7 @@ public class GethService extends Service {
|
|||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
System.loadLibrary("gethraw");
|
||||
System.loadLibrary("geth");
|
||||
System.loadLibrary("statusgo");
|
||||
|
||||
if (!isGethInitialized) {
|
||||
isGethInitialized = true;
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.io.File;
|
||||
import com.statusim.Jail.JailPackage;
|
||||
|
||||
import com.lwansbrough.RCTCamera.*;
|
||||
import com.i18n.reactnativei18n.ReactNativeI18n;
|
||||
|
@ -176,6 +177,7 @@ public class MainActivity extends ReactActivity {
|
|||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new JailPackage(),
|
||||
new RealmReactPackage(),
|
||||
new VectorIconsPackage(),
|
||||
new ReactNativeContacts(),
|
||||
|
|
|
@ -18,7 +18,11 @@ include ':react-native-linear-gradient'
|
|||
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
|
||||
include ':ReactNativeAndroidSmsListener'
|
||||
project(':ReactNativeAndroidSmsListener').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-android-sms-listener/android')
|
||||
|
||||
include ':react-native-status'
|
||||
project(':react-native-status').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-status/android')
|
||||
include ':react-native-camera'
|
||||
project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
|
||||
|
||||
include ':react-native-orientation', ':app'
|
||||
project(':react-native-orientation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation/android')
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"react-native-randombytes": "^2.1.0",
|
||||
"react-native-vector-icons": "^1.3.4",
|
||||
"react-native-orientation": "^1.17.0",
|
||||
"realm": "^0.11.1"
|
||||
"realm": "^0.11.1",
|
||||
"react-native-status": "git+ssh://git@github.com/status-im/react-native-status"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
status.command({
|
||||
name: "location",
|
||||
description: "Send location",
|
||||
color: "#9a5dcf"
|
||||
}).param({
|
||||
name: "address",
|
||||
type: status.types.STRING
|
||||
});
|
||||
|
||||
var phones = [
|
||||
{
|
||||
number: "89171111111",
|
||||
description: "Number format 1"
|
||||
},
|
||||
{
|
||||
number: "89371111111",
|
||||
description: "Number format 1"
|
||||
},
|
||||
{
|
||||
number: "+79171111111",
|
||||
description: "Number format 2"
|
||||
},
|
||||
{
|
||||
number: "9171111111",
|
||||
description: "Number format 3"
|
||||
}
|
||||
];
|
||||
|
||||
function suggestionsContainerStyle(suggestionsCount) {
|
||||
return {
|
||||
marginVertical: 1,
|
||||
marginHorizontal: 0,
|
||||
height: Math.min(150, (56 * suggestionsCount)),
|
||||
backgroundColor: "white",
|
||||
borderRadius: 5
|
||||
};
|
||||
}
|
||||
|
||||
var suggestionContainerStyle = {
|
||||
paddingLeft: 16,
|
||||
backgroundColor: "white"
|
||||
};
|
||||
|
||||
var suggestionSubContainerStyle = {
|
||||
height: 56,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#0000001f"
|
||||
};
|
||||
|
||||
var valueStyle = {
|
||||
marginTop: 9,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#000000de"
|
||||
};
|
||||
|
||||
var descriptionStyle = {
|
||||
marginTop: 1.5,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#838c93de"
|
||||
};
|
||||
|
||||
function startsWith(str1, str2) {
|
||||
// String.startsWith(...) doesn't work in otto
|
||||
return str1.lastIndexOf(str2, 0) == 0 && str1 != str2;
|
||||
}
|
||||
|
||||
function phoneSuggestions(params) {
|
||||
var ph, suggestions;
|
||||
if (!params.value || params.value == "") {
|
||||
ph = phones;
|
||||
} else {
|
||||
ph = phones.filter(function (phone) {
|
||||
return startsWith(phone.number, params.value);
|
||||
});
|
||||
}
|
||||
|
||||
if (ph.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
suggestions = ph.map(function (phone) {
|
||||
return status.components.touchable(
|
||||
{onPress: [status.events.SET_VALUE, phone.number]},
|
||||
status.components.view(suggestionContainerStyle,
|
||||
[status.components.view(suggestionSubContainerStyle,
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
phone.number
|
||||
),
|
||||
status.components.text(
|
||||
{style: descriptionStyle},
|
||||
phone.description
|
||||
)
|
||||
])])
|
||||
);
|
||||
});
|
||||
|
||||
return status.components.scrollView(
|
||||
suggestionsContainerStyle(ph.length),
|
||||
suggestions
|
||||
);
|
||||
}
|
||||
|
||||
status.response({
|
||||
name: "phone",
|
||||
description: "Send phone number",
|
||||
color: "#5fc48d",
|
||||
params: [{
|
||||
name: "phone",
|
||||
type: status.types.PHONE_NUMBER,
|
||||
suggestions: phoneSuggestions
|
||||
}],
|
||||
handler: function (params) {
|
||||
return {
|
||||
event: "sign-up",
|
||||
params: [params.value]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
status.command({
|
||||
name: "help",
|
||||
description: "Help",
|
||||
color: "#7099e6",
|
||||
params: [{
|
||||
name: "query",
|
||||
type: status.types.STRING
|
||||
}]
|
||||
});
|
||||
|
||||
status.response({
|
||||
name: "confirmation-code",
|
||||
color: "#7099e6",
|
||||
description: "Confirmation code",
|
||||
params: [{
|
||||
name: "code",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
handler: function (params) {
|
||||
return {
|
||||
event: "confirm-sign-up",
|
||||
params: [params.value]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
status.response({
|
||||
name: "keypair",
|
||||
color: "#7099e6",
|
||||
description: "Keypair password",
|
||||
icon: "icon_lock_white",
|
||||
params: [{
|
||||
name: "password",
|
||||
type: status.types.PASSWORD
|
||||
}],
|
||||
handler: function (params) {
|
||||
return {
|
||||
event: "save-password",
|
||||
params: [params.value]
|
||||
};
|
||||
},
|
||||
preview: function (params) {
|
||||
return status.components.text(
|
||||
{
|
||||
style: {
|
||||
marginTop: 5,
|
||||
marginHorizontal: 0,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "black"
|
||||
}
|
||||
}, "*****");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
var _status_catalog = {
|
||||
commands: {},
|
||||
responses: {}
|
||||
};
|
||||
|
||||
function Command() {
|
||||
}
|
||||
function Response() {
|
||||
}
|
||||
|
||||
Command.prototype.addToCatalog = function () {
|
||||
_status_catalog.commands[this.name] = this;
|
||||
};
|
||||
|
||||
Command.prototype.param = function (parameter) {
|
||||
this.params.push(parameter);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Command.prototype.create = function (com) {
|
||||
this.name = com.name;
|
||||
this.description = com.description;
|
||||
this.handler = com.handler;
|
||||
this.color = com.color;
|
||||
this.icon = com.icon;
|
||||
this.params = com.params || [];
|
||||
this.preview = com.preview;
|
||||
this.addToCatalog();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
Response.prototype = Object.create(Command.prototype);
|
||||
Response.prototype.addToCatalog = function () {
|
||||
_status_catalog.responses[this.name] = this;
|
||||
};
|
||||
Response.prototype.onReceiveResponse = function (handler) {
|
||||
this.onReceive = handler;
|
||||
};
|
||||
|
||||
function call(pathStr, paramsStr) {
|
||||
var params = JSON.parse(paramsStr),
|
||||
path = JSON.parse(pathStr),
|
||||
fn, res;
|
||||
|
||||
fn = path.reduce(function (catalog, name) {
|
||||
if (catalog && catalog[name]) {
|
||||
return catalog[name];
|
||||
}
|
||||
},
|
||||
_status_catalog
|
||||
);
|
||||
|
||||
if(!fn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
res = fn(params);
|
||||
|
||||
return JSON.stringify(res);
|
||||
}
|
||||
|
||||
function text(options, s) {
|
||||
return ['text', options, s];
|
||||
}
|
||||
|
||||
function view(options, elements) {
|
||||
return ['view', options].concat(elements);
|
||||
}
|
||||
|
||||
function image(options) {
|
||||
return ['image', options];
|
||||
}
|
||||
|
||||
function touchable(options, element) {
|
||||
return ['touchable', options, element];
|
||||
}
|
||||
|
||||
function scrollView(options, elements) {
|
||||
return ['scroll-view', options].concat(elements);
|
||||
}
|
||||
|
||||
var status = {
|
||||
command: function (n, d, h) {
|
||||
var command = new Command();
|
||||
return command.create(n, d, h);
|
||||
},
|
||||
response: function (n, d, h) {
|
||||
var response = new Response();
|
||||
return response.create(n, d, h);
|
||||
},
|
||||
types: {
|
||||
STRING: 'string',
|
||||
PHONE_NUMBER: 'phone-number',
|
||||
PASSWORD: 'password'
|
||||
},
|
||||
events: {
|
||||
SET_VALUE: 'set-value'
|
||||
},
|
||||
components: {
|
||||
view: view,
|
||||
text: text,
|
||||
image: image,
|
||||
touchable: touchable,
|
||||
scrollView: scrollView
|
||||
}
|
||||
};
|
|
@ -83,7 +83,6 @@
|
|||
(dispatch [:load-user-phone-number])
|
||||
(dispatch [:load-contacts])
|
||||
;; load commands from remote server (todo: uncomment)
|
||||
;; (dispatch [:load-commands])
|
||||
(dispatch [:init-console-chat])
|
||||
(dispatch [:init-chat])
|
||||
(init-back-button-handler!)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
(ns status-im.chat.constants)
|
||||
|
||||
(def input-height 56)
|
||||
(def request-info-height 61)
|
||||
(def response-height-normal 211)
|
||||
(def minimum-suggestion-height (+ input-height request-info-height))
|
|
@ -3,7 +3,6 @@
|
|||
[status-im.models.commands :as commands]
|
||||
[clojure.string :as str]
|
||||
[status-im.components.styles :refer [default-chat-color]]
|
||||
[status-im.chat.styles.response :refer [request-info-height response-height-normal]]
|
||||
[status-im.chat.suggestions :as suggestions]
|
||||
[status-im.protocol.api :as api]
|
||||
[status-im.models.messages :as messages]
|
||||
|
@ -19,8 +18,8 @@
|
|||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||
[status-im.utils.phone-number :refer [format-phone-number]]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.chat.handlers.animation :refer [update-response-height
|
||||
get-response-height]]))
|
||||
[status-im.components.jail :as j]
|
||||
[status-im.commands.utils :refer [generate-hiccup]]))
|
||||
|
||||
(register-handler :set-show-actions
|
||||
(fn [db [_ show-actions]]
|
||||
|
@ -44,35 +43,64 @@
|
|||
(assoc-in [:chats current-chat-id :command-input] {})
|
||||
(update-in [:chats current-chat-id :input-text] safe-trim))))
|
||||
|
||||
(defn invoke-suggestions-handler!
|
||||
[{:keys [current-chat-id] :as db} _]
|
||||
(let [{:keys [command content]} (get-in db [:chats current-chat-id :command-input])
|
||||
{:keys [name type]} command
|
||||
path [(if (= :command type) :commands :responses)
|
||||
name
|
||||
:params
|
||||
0
|
||||
:suggestions]
|
||||
params {:value content}]
|
||||
(j/call current-chat-id
|
||||
path
|
||||
params
|
||||
#(dispatch [:suggestions-handler {:command command
|
||||
:content content
|
||||
:chat-id current-chat-id} %]))))
|
||||
|
||||
(register-handler :start-cancel-command
|
||||
(u/side-effect!
|
||||
(fn [db _]
|
||||
(dispatch [:animate-cancel-command]))))
|
||||
|
||||
(register-handler :set-chat-command-content
|
||||
[(after invoke-suggestions-handler!)]
|
||||
(fn [{:keys [current-chat-id] :as db} [_ content]]
|
||||
(as-> db db
|
||||
(commands/set-chat-command-content db content)
|
||||
(assoc-in db [:chats current-chat-id :input-text] nil)
|
||||
(if (commands/get-chat-command-to-msg-id db)
|
||||
(update-response-height db)
|
||||
db))))
|
||||
(assoc-in db [:chats current-chat-id :input-text] nil))))
|
||||
|
||||
(defn update-input-text
|
||||
[{:keys [current-chat-id] :as db} text]
|
||||
(assoc-in db [:chats current-chat-id :input-text] text))
|
||||
|
||||
(defn invoke-command-preview!
|
||||
[{:keys [current-chat-id staged-command]} _]
|
||||
(let [{:keys [command content]} staged-command
|
||||
{:keys [name type]} command
|
||||
path [(if (= :command type) :commands :responses)
|
||||
name
|
||||
:preview]
|
||||
params {:value content}]
|
||||
(j/call current-chat-id
|
||||
path
|
||||
params
|
||||
#(dispatch [:command-preview current-chat-id %]))))
|
||||
|
||||
(register-handler :stage-command
|
||||
(after invoke-command-preview!)
|
||||
(fn [{:keys [current-chat-id] :as db} _]
|
||||
(let [db (update-input-text db nil)
|
||||
{:keys [command content]}
|
||||
(get-in db [:chats current-chat-id :command-input])
|
||||
command-info {:command command
|
||||
:content content
|
||||
:handler (:handler command)}]
|
||||
:content content}]
|
||||
(-> db
|
||||
(assoc-in [:chats current-chat-id :command-input :command] nil)
|
||||
(commands/stage-command command-info)))))
|
||||
;(assoc-in [:chats current-chat-id :command-input :command] nil)
|
||||
(commands/stage-command command-info)
|
||||
(assoc :staged-command command-info)))))
|
||||
|
||||
(register-handler :set-message-input []
|
||||
(fn [db [_ input]]
|
||||
|
@ -85,8 +113,10 @@
|
|||
(.blur message-input)))))
|
||||
|
||||
(register-handler :set-response-chat-command
|
||||
[(after #(dispatch [:command-edit-mode]))
|
||||
(after #(dispatch [:animate-show-response]))]
|
||||
[(after invoke-suggestions-handler!)
|
||||
(after #(dispatch [:command-edit-mode]))
|
||||
;(after #(dispatch [:animate-show-response]))
|
||||
]
|
||||
(fn [db [_ to-msg-id command-key]]
|
||||
(commands/set-response-chat-command db to-msg-id command-key)))
|
||||
|
||||
|
@ -143,8 +173,8 @@
|
|||
|
||||
(defn prepare-message
|
||||
[{:keys [identity current-chat-id] :as db} _]
|
||||
(let [text (get-in db [:chats current-chat-id :input-text])
|
||||
{:keys [command]} (suggestions/check-suggestion db (str text " "))
|
||||
(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)
|
||||
|
@ -159,17 +189,18 @@
|
|||
(commands/set-chat-command db command)
|
||||
(assoc db :new-message (when-not (str/blank? text) message)))))
|
||||
|
||||
(defn prepare-command [identity chat-id staged-command]
|
||||
(let [command-key (get-in staged-command [:command :command])
|
||||
content {:command (name command-key)
|
||||
:content (:content staged-command)}]
|
||||
{:msg-id (random/id)
|
||||
:from identity
|
||||
:to chat-id
|
||||
:content content
|
||||
:content-type content-type-command
|
||||
:outgoing true
|
||||
:handler (:handler staged-command)}))
|
||||
(defn prepare-command
|
||||
[identity chat-id {:keys [preview preview-string content command]}]
|
||||
(let [content {:command (command :name)
|
||||
:content content}]
|
||||
{:msg-id (random/id)
|
||||
:from identity
|
||||
:to chat-id
|
||||
:content content
|
||||
:content-type content-type-command
|
||||
:outgoing true
|
||||
:preview preview-string
|
||||
:rendered-preview preview}))
|
||||
|
||||
(defn prepare-staged-commans
|
||||
[{:keys [current-chat-id identity] :as db} _]
|
||||
|
@ -222,7 +253,22 @@
|
|||
(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 :handler))))
|
||||
(messages/save-message current-chat-id
|
||||
(dissoc new-command :rendered-preview))))
|
||||
|
||||
(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 %])))))
|
||||
|
||||
(defn handle-commands
|
||||
[{:keys [new-commands]}]
|
||||
|
@ -241,6 +287,8 @@
|
|||
((after send-message!))
|
||||
((after save-message-to-realm!))
|
||||
((after save-commands-to-realm!))
|
||||
;; todo maybe it is better to track if it was handled or not
|
||||
((after invoke-commands-handlers!))
|
||||
((after handle-commands))))
|
||||
|
||||
(register-handler :unstage-command
|
||||
|
@ -249,7 +297,8 @@
|
|||
|
||||
(register-handler :set-chat-command
|
||||
[(after #(dispatch [:command-edit-mode]))
|
||||
(after #(dispatch [:animate-show-response]))]
|
||||
;(after #(dispatch [:animate-show-response]))
|
||||
]
|
||||
(fn [db [_ command-key]]
|
||||
(commands/set-chat-command db command-key)))
|
||||
|
||||
|
@ -294,9 +343,14 @@
|
|||
([{:keys [messages current-chat-id] :as db} _]
|
||||
(assoc-in db [:chats current-chat-id :messages] messages)))
|
||||
|
||||
(defn load-commands!
|
||||
[{:keys [current-chat-id]}]
|
||||
(dispatch [:load-commands! current-chat-id]))
|
||||
|
||||
(register-handler :init-chat
|
||||
(-> load-messages!
|
||||
((enrich init-chat))
|
||||
((after load-commands!))
|
||||
debug))
|
||||
|
||||
(defn initialize-chats
|
||||
|
@ -340,9 +394,9 @@
|
|||
|
||||
(defmethod nav/preload-data! :chat
|
||||
[{:keys [current-chat-id] :as db} [_ _ id]]
|
||||
(let [chat-id (or id current-chat-id)
|
||||
(let [chat-id (or id current-chat-id)
|
||||
messages (get-in db [:chats chat-id :messages])
|
||||
db' (assoc db :current-chat-id chat-id)]
|
||||
db' (assoc db :current-chat-id chat-id)]
|
||||
(if (seq messages)
|
||||
db'
|
||||
(-> db'
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
(ns status-im.chat.handlers.animation
|
||||
(:require [re-frame.core :refer [register-handler after dispatch]]
|
||||
(:require [re-frame.core :refer [register-handler after dispatch debug]]
|
||||
[re-frame.middleware :refer [path]]
|
||||
[status-im.models.commands :as commands]
|
||||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||
[status-im.chat.styles.message-input :refer [input-height]]
|
||||
[status-im.chat.styles.response :refer [request-info-height response-height-normal]]
|
||||
[status-im.chat.styles.response-suggestions :as response-suggestions-styles]
|
||||
[status-im.chat.constants :refer [input-height request-info-height
|
||||
response-height-normal minimum-suggestion-height]]
|
||||
[status-im.constants :refer [response-input-hiding-duration]]))
|
||||
|
||||
(def zero-height input-height)
|
||||
;; todo magic value
|
||||
(def middle-height 270)
|
||||
|
||||
(defn animation-handler
|
||||
([name handler] (animation-handler name nil handler))
|
||||
|
@ -19,25 +18,21 @@
|
|||
(after #(dispatch [:text-edit-mode]))
|
||||
(fn [db _]
|
||||
(assoc db
|
||||
:to-response-height zero-height
|
||||
:to-response-height input-height
|
||||
:messages-offset 0)))
|
||||
|
||||
(defn get-response-height [db]
|
||||
(let [command (commands/get-chat-command db)
|
||||
text (commands/get-chat-command-content db)
|
||||
suggestions (get-content-suggestions command text)
|
||||
suggestions-height (reduce + 0 (map #(if (:header %)
|
||||
response-suggestions-styles/header-height
|
||||
response-suggestions-styles/suggestion-height)
|
||||
suggestions))]
|
||||
(+ zero-height
|
||||
(defn get-response-height
|
||||
[{:keys [current-chat-id] :as db}]
|
||||
(let [suggestions (get-in db [:suggestions current-chat-id])
|
||||
suggestions-height (if suggestions middle-height 0)]
|
||||
(+ input-height
|
||||
(min response-height-normal (+ suggestions-height request-info-height)))))
|
||||
|
||||
(defn update-response-height [db]
|
||||
(assoc-in db [:animations :to-response-height] (get-response-height db)))
|
||||
|
||||
(register-handler :animate-show-response
|
||||
(after #(dispatch [:command-edit-mode]))
|
||||
[(after #(dispatch [:command-edit-mode]))]
|
||||
(fn [db _]
|
||||
(-> db
|
||||
(assoc-in [:animations :messages-offset] request-info-height)
|
||||
|
@ -54,26 +49,28 @@
|
|||
db))))
|
||||
|
||||
(register-handler :fix-response-height
|
||||
(fn [db [_ vy current]]
|
||||
(fn [{:keys [current-chat-id] :as db} [_ vy current]]
|
||||
(let [max-height (get-in db [:animations :response-height-max])
|
||||
;; todo magic value
|
||||
middle 270
|
||||
moving-down? (pos? vy)
|
||||
moving-up? (not moving-down?)
|
||||
under-middle-position? (<= current middle)
|
||||
under-middle-position? (<= current middle-height)
|
||||
over-middle-position? (not under-middle-position?)
|
||||
min-height (+ zero-height request-info-height)
|
||||
new-fixed (cond (and under-middle-position? moving-down?)
|
||||
min-height
|
||||
suggestions (get-in db [:suggestions current-chat-id])
|
||||
new-fixed (cond (not suggestions)
|
||||
minimum-suggestion-height
|
||||
|
||||
(and under-middle-position? moving-up?)
|
||||
middle
|
||||
middle-height
|
||||
|
||||
(and over-middle-position? moving-down?)
|
||||
middle
|
||||
middle-height
|
||||
|
||||
(and over-middle-position? moving-up?)
|
||||
max-height)]
|
||||
max-height
|
||||
|
||||
(and under-middle-position?
|
||||
moving-down?)
|
||||
minimum-suggestion-height)]
|
||||
(-> db
|
||||
(assoc-in [:animations :to-response-height] new-fixed)
|
||||
(update-in [:animations :response-height-changed] inc)))))
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
[status-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
|
||||
[status-im.components.toolbar :refer [toolbar]]
|
||||
[status-im.chat.views.message :refer [chat-message]]
|
||||
[status-im.chat.views.content-suggestions :refer [content-suggestions-view]]
|
||||
[status-im.chat.views.suggestions :refer [suggestions-view]]
|
||||
[status-im.chat.views.response :refer [response-view]]
|
||||
[status-im.chat.views.new-message :refer [chat-message-new]]
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
(dispatch [:received-msg
|
||||
{:msg-id msg-id
|
||||
:content (command-content
|
||||
:keypair-password
|
||||
:keypair
|
||||
(label :t/keypair-generated))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
|
@ -184,6 +184,9 @@
|
|||
(def console-chat
|
||||
{:chat-id "console"
|
||||
:name "console"
|
||||
; todo remove/change dapp config fot console
|
||||
:dapp-url "http://localhost:8185/resources"
|
||||
:dapp-hash 858845357
|
||||
:color default-chat-color
|
||||
:group-chat false
|
||||
:is-active true
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
(ns status-im.chat.styles.content-suggestions
|
||||
(:require [status-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
|
||||
(def suggestion-height 56)
|
||||
|
||||
(def suggestion-container
|
||||
{:flexDirection :column
|
||||
:paddingLeft 16
|
||||
{:paddingLeft 16
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def suggestion-sub-container
|
||||
|
@ -37,7 +36,7 @@
|
|||
:color text2-color})
|
||||
|
||||
(defn suggestions-container [suggestions-count]
|
||||
{:flexDirection :row
|
||||
{:flex 1
|
||||
:marginVertical 1
|
||||
:marginHorizontal 0
|
||||
:height (min 150 (* suggestion-height suggestions-count))
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
(ns status-im.chat.styles.message
|
||||
(:require [status-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
selected-message-color
|
||||
online-color
|
||||
text1-color
|
||||
text2-color]]
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
selected-message-color
|
||||
online-color
|
||||
text1-color
|
||||
text2-color]]
|
||||
[status-im.constants :refer [text-content-type
|
||||
content-type-command]]))
|
||||
content-type-command]]))
|
||||
|
||||
(def style-message-text
|
||||
{:fontSize 14
|
||||
|
@ -153,6 +153,14 @@
|
|||
:backgroundColor (:color command)
|
||||
:transform [{:scale scale}]})
|
||||
|
||||
(def command-image-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:right 0
|
||||
:width 24
|
||||
:height 24
|
||||
:alignItems :center})
|
||||
|
||||
(def command-request-image
|
||||
{:position :absolute
|
||||
:top 9
|
||||
|
@ -185,11 +193,10 @@
|
|||
:color color-white})
|
||||
|
||||
(def command-image
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:right 0
|
||||
:width 12
|
||||
:height 13})
|
||||
{:margin-top 5
|
||||
:width 12
|
||||
:height 13
|
||||
:tint-color :#a9a9a9cc})
|
||||
|
||||
(def command-text
|
||||
(merge style-message-text
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
(ns status-im.chat.styles.message-input
|
||||
(:require [status-im.components.styles :refer [color-white
|
||||
color-blue]]))
|
||||
|
||||
(def input-height 56)
|
||||
color-blue]]
|
||||
[status-im.chat.constants :refer [input-height]]))
|
||||
|
||||
(def message-input-container
|
||||
{:flex 1
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
text2-color
|
||||
chat-background
|
||||
color-black]]
|
||||
[status-im.chat.styles.message-input :refer [input-height]]))
|
||||
|
||||
(def response-height-normal 211)
|
||||
(def request-info-height 61)
|
||||
[status-im.chat.constants :refer [input-height request-info-height
|
||||
response-height-normal]]))
|
||||
|
||||
(def drag-container
|
||||
{:height 16
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
(ns status-im.chat.styles.response-suggestions
|
||||
(:require [status-im.components.styles :refer [font
|
||||
font-medium
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
|
||||
(def header-height 50)
|
||||
(def suggestion-height 56)
|
||||
|
||||
(def header-container
|
||||
{:paddingLeft 16
|
||||
:height header-height
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def header-text
|
||||
{:marginTop 18
|
||||
:fontSize 13
|
||||
:fontFamily font-medium
|
||||
:color text2-color})
|
||||
|
||||
(def suggestion-container
|
||||
{:flexDirection :column
|
||||
:paddingLeft 16
|
||||
:height suggestion-height
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def suggestion-sub-container
|
||||
{:height suggestion-height
|
||||
:borderBottomWidth 1
|
||||
:borderBottomColor separator-color})
|
||||
|
||||
(def value-text
|
||||
{:marginTop 10
|
||||
:fontSize 12
|
||||
:fontFamily font
|
||||
:color text1-color})
|
||||
|
||||
(def description-text
|
||||
{:marginTop 2
|
||||
:fontSize 12
|
||||
:fontFamily font
|
||||
:color text2-color})
|
||||
|
||||
(def suggestions-container
|
||||
{:flexDirection :row
|
||||
:flex 1
|
||||
:marginVertical 1
|
||||
:marginHorizontal 0
|
||||
:backgroundColor color-white
|
||||
:borderRadius 5})
|
|
@ -1,15 +1,15 @@
|
|||
(ns status-im.chat.subs
|
||||
(:require-macros [reagent.ratom :refer [reaction]])
|
||||
(:require [re-frame.core :refer [register-sub dispatch subscribe]]
|
||||
(:require [re-frame.core :refer [register-sub dispatch subscribe path]]
|
||||
[status-im.db :as db]
|
||||
;todo handlers in subs?...
|
||||
[status-im.chat.suggestions :refer
|
||||
[get-suggestions typing-command?]]
|
||||
[status-im.models.commands :as commands]
|
||||
[status-im.constants :refer [response-suggesstion-resize-duration]]
|
||||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||
[status-im.chat.views.plain-message :as plain-message]
|
||||
[status-im.chat.views.command :as command]))
|
||||
[status-im.chat.views.command :as command]
|
||||
[status-im.chat.constants :as c]))
|
||||
|
||||
(register-sub :chat-properties
|
||||
(fn [db [_ properties]]
|
||||
|
@ -53,6 +53,18 @@
|
|||
(fn [db _]
|
||||
(reaction (commands/get-commands @db))))
|
||||
|
||||
(register-sub :get-responses
|
||||
(fn [db _]
|
||||
(let [current-chat (@db :current-chat-id)]
|
||||
(reaction (or (get-in @db [:chats current-chat :responses]) {})))))
|
||||
|
||||
(register-sub :get-commands-and-responses
|
||||
(fn [db _]
|
||||
(let [current-chat (@db :current-chat-id)]
|
||||
(reaction _ (or (->> (get-in @db [:chats current-chat])
|
||||
((juxt :commands :responses))
|
||||
(apply merge)) {})))))
|
||||
|
||||
(register-sub :get-chat-input-text
|
||||
(fn [db _]
|
||||
(->> [:chats (:current-chat-id @db) :input-text]
|
||||
|
@ -108,12 +120,10 @@
|
|||
|
||||
(register-sub :get-content-suggestions
|
||||
(fn [db _]
|
||||
(let [command (reaction (commands/get-chat-command @db))
|
||||
text (reaction (commands/get-chat-command-content @db))]
|
||||
(reaction (get-content-suggestions @command @text)))))
|
||||
(reaction (get-in @db [:suggestions (:current-chat-id @db)]))))
|
||||
|
||||
(register-sub :command?
|
||||
(fn [db ]
|
||||
(fn [db]
|
||||
(->> (get-in @db [:edit-mode (:current-chat-id @db)])
|
||||
(= :command)
|
||||
(reaction))))
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
(ns status-im.chat.suggestions
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[status-im.db :as db]
|
||||
[status-im.models.commands :refer [commands
|
||||
suggestions
|
||||
get-commands
|
||||
get-chat-command-request
|
||||
get-chat-command-to-msg-id
|
||||
clear-staged-commands]]
|
||||
[status-im.models.commands :refer [get-commands
|
||||
get-chat-command-request
|
||||
get-chat-command-to-msg-id
|
||||
clear-staged-commands]]
|
||||
[status-im.utils.utils :refer [log on-error http-get]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(defn suggestion? [text]
|
||||
(= (get text 0) "!"))
|
||||
|
||||
(defn get-suggestions [db text]
|
||||
(if (suggestion? text)
|
||||
;; TODO change 'commands' to 'suggestions'
|
||||
(filterv #(.startsWith (:text %) text) (get-commands db))
|
||||
[]))
|
||||
(defn can-be-suggested? [text]
|
||||
(fn [{:keys [name]}]
|
||||
(.startsWith (str "!" name) text)))
|
||||
|
||||
(defn get-suggestions
|
||||
[{:keys [current-chat-id] :as db} text]
|
||||
(let [commands (get-in db [:chats current-chat-id :commands])]
|
||||
(if (suggestion? text)
|
||||
(filter (fn [[_ v]] ((can-be-suggested? text) v)) commands)
|
||||
[])))
|
||||
|
||||
(defn get-command [db text]
|
||||
(when (suggestion? text)
|
||||
|
@ -45,22 +48,13 @@
|
|||
staged-commands))
|
||||
(clear-staged-commands db)))
|
||||
|
||||
(defn execute-commands-js [body]
|
||||
(.eval js/window body)
|
||||
(let [commands (.-commands js/window)]
|
||||
(dispatch [:set-commands (map #(update % :command keyword)
|
||||
(js->clj commands :keywordize-keys true))])))
|
||||
|
||||
(defn load-commands []
|
||||
(http-get "chat-commands.js" execute-commands-js nil))
|
||||
|
||||
(defn check-suggestion [db message]
|
||||
(when-let [suggestion-text (when (string? message)
|
||||
(re-matches #"^![^\s]+\s" message))]
|
||||
(let [suggestion-text' (s/trim suggestion-text)
|
||||
[suggestion] (filter #(= suggestion-text' (:text %))
|
||||
(get-commands db))]
|
||||
suggestion)))
|
||||
(let [suggestion-text' (s/trim suggestion-text)]
|
||||
(->> (get-commands db)
|
||||
(filter #(= suggestion-text' (->> % second :name (str "!"))))
|
||||
first))))
|
||||
|
||||
(defn typing-command? [db]
|
||||
(-> db
|
||||
|
|
|
@ -35,3 +35,4 @@
|
|||
[touchable-highlight {:on-press cancel-command-input}
|
||||
[view st/cancel-container
|
||||
[icon :close-gray st/cancel-icon]]])
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
(ns status-im.chat.views.content-suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
icon
|
||||
text
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
[status-im.chat.styles.content-suggestions :as st]
|
||||
[status-im.utils.listview :refer [to-datasource]]))
|
||||
|
||||
(defn set-command-content [content]
|
||||
(dispatch [:set-chat-command-content content]))
|
||||
|
||||
(defn suggestion-list-item [{:keys [value description]}]
|
||||
[touchable-highlight {:onPress #(set-command-content value)}
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[text {:style st/value-text} value]
|
||||
[text {:style st/description-text} description]]]])
|
||||
|
||||
(defn render-row [row _ _]
|
||||
(list-item [suggestion-list-item row]))
|
||||
|
||||
(defview content-suggestions-view []
|
||||
[suggestions [:get-content-suggestions]]
|
||||
(when-let [values (not-empty (filter :value suggestions))]
|
||||
[view st/container
|
||||
[touchable-highlight {:style st/drag-down-touchable
|
||||
;; TODO hide suggestions?
|
||||
:onPress (fn [])}
|
||||
[view [icon :drag_down st/drag-down-icon]]]
|
||||
[view (st/suggestions-container (count values))
|
||||
[list-view {:dataSource (to-datasource values)
|
||||
:keyboardShouldPersistTaps true
|
||||
:renderRow render-row}]]]))
|
|
@ -1,11 +1,12 @@
|
|||
(ns status-im.chat.views.message
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [clojure.string :as s]
|
||||
[re-frame.core :refer [subscribe dispatch]]
|
||||
[reagent.core :as r]
|
||||
[status-im.components.react :refer [view
|
||||
animated-view
|
||||
text
|
||||
image
|
||||
animated-view
|
||||
touchable-highlight]]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.chat.views.request-message :refer [message-content-command-request]]
|
||||
|
@ -55,24 +56,48 @@
|
|||
[view st/track-mark]
|
||||
[text {:style st/track-duration-text} "03:39"]]])
|
||||
|
||||
(defn message-content-command [content]
|
||||
(let [commands-atom (subscribe [:get-commands])]
|
||||
(fn [content]
|
||||
(let [commands @commands-atom
|
||||
{:keys [command content]}
|
||||
(parse-command-msg-content commands content)]
|
||||
[view st/content-command-view
|
||||
[view st/command-container
|
||||
[view (st/command-view command)
|
||||
[text {:style st/command-name}
|
||||
(:text command)]]]
|
||||
[image {:source (:icon command)
|
||||
:style st/command-image}]
|
||||
[text {:style st/command-text}
|
||||
;; TODO isn't smart
|
||||
(if (= (:command command) :keypair-password)
|
||||
"******"
|
||||
content)]]))))
|
||||
(defview message-content-command [content preview]
|
||||
[commands [:get-commands-and-responses]]
|
||||
(let [{:keys [command content]} (parse-command-msg-content commands content)
|
||||
{:keys [name icon type]} command]
|
||||
[view st/content-command-view
|
||||
[view st/command-container
|
||||
[view (st/command-view command)
|
||||
[text {:style st/command-name}
|
||||
(str (if (= :command type) "!" "") name)]]]
|
||||
(when icon
|
||||
[view st/command-image-view
|
||||
[image {:source {:uri icon}
|
||||
:style st/command-image}]])
|
||||
(if preview
|
||||
preview
|
||||
[text {:style st/command-text} content])]))
|
||||
|
||||
(defn set-chat-command [msg-id command]
|
||||
(dispatch [:set-response-chat-command msg-id (keyword (:name command))]))
|
||||
|
||||
(defn label [{:keys [command]}]
|
||||
(->> (when command (name command))
|
||||
(str "request-")))
|
||||
|
||||
;; todo remove (merging leftover)
|
||||
#_(defview message-content-command-request
|
||||
[{:keys [msg-id content from incoming-group]}]
|
||||
[commands [:get-responses]]
|
||||
(let [{:keys [command content]} (parse-command-request commands content)]
|
||||
[touchable-highlight {:onPress #(set-chat-command msg-id command)
|
||||
:accessibility-label (label command)}
|
||||
[view st/comand-request-view
|
||||
[view st/command-request-message-view
|
||||
(when incoming-group
|
||||
[text {:style st/command-request-from-text} from])
|
||||
[text {:style st/style-message-text} content]]
|
||||
[view (st/command-request-image-view command)
|
||||
[image {:source {:uri (:icon command)}
|
||||
:style st/command-request-image}]]
|
||||
(when-let [request-text (:request-text command)]
|
||||
[view st/command-request-text-view
|
||||
[text {:style st/style-sub-text} request-text]])]]))
|
||||
|
||||
(defn message-view
|
||||
[message content]
|
||||
|
@ -103,9 +128,9 @@
|
|||
[message-content-status message])
|
||||
|
||||
(defmethod message-content content-type-command
|
||||
[wrapper {:keys [content] :as message}]
|
||||
[wrapper {:keys [content rendered-preview] :as message}]
|
||||
[wrapper message
|
||||
[message-view message [message-content-command content]]])
|
||||
[message-view message [message-content-command content rendered-preview]]])
|
||||
|
||||
(defmethod message-content :default
|
||||
[wrapper {:keys [content-type content] :as message}]
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
icon
|
||||
touchable-highlight
|
||||
text-input]]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.chat.views.plain-message :as plain-message]
|
||||
[status-im.chat.views.command :as command]
|
||||
[status-im.chat.styles.message-input :as st]
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
(case (:command command)
|
||||
:phone {:input-options {:keyboardType :phone-pad}
|
||||
:validator valid-mobile-number?}
|
||||
:keypair-password {:input-options {:secureTextEntry true}}
|
||||
:keypair {:input-options {:secureTextEntry true}}
|
||||
:confirmation-code {:input-options {:keyboardType :numeric}}
|
||||
:money {:input-options {:keyboardType :numeric}}
|
||||
:request {:input-options {:keyboardType :numeric}}
|
||||
(throw (js/Error. "Uknown command type"))))])
|
||||
;; todo maybe nil is finr for now :)
|
||||
nil #_(throw (js/Error. "Uknown command type"))))])
|
||||
|
||||
(defview chat-message-new []
|
||||
[staged-commands [:get-chat-staged-commands]]
|
||||
|
|
|
@ -24,15 +24,16 @@
|
|||
(defn button-animation-logic [{:keys [command? val]}]
|
||||
(fn [_]
|
||||
(let [to-scale (if @command? 0 1)]
|
||||
(anim/start (anim/spring val {:toValue to-scale})))))
|
||||
(anim/start (anim/spring val {:toValue to-scale
|
||||
:tension 30})))))
|
||||
|
||||
(defn list-container [min]
|
||||
(fn [{:keys [command? width]}]
|
||||
(let [n-width (if @command? min 56)
|
||||
delay (if @command? 100 0)]
|
||||
delay (if @command? 100 0)]
|
||||
(anim/start (anim/timing width {:toValue n-width
|
||||
:duration response-input-hiding-duration
|
||||
:delay delay})))))
|
||||
:delay delay})))))
|
||||
|
||||
(defn commands-button []
|
||||
(let [command? (subscribe [:command?])
|
||||
|
@ -62,19 +63,20 @@
|
|||
(fn [_]
|
||||
(let [to-scale (if @command? 0 1)]
|
||||
(when-not @command? (anim/set-value width 56))
|
||||
(anim/start (anim/spring val {:toValue to-scale})
|
||||
(anim/start (anim/spring val {:toValue to-scale
|
||||
:tension 30})
|
||||
(fn [e]
|
||||
(when (and @command? (.-finished e))
|
||||
(anim/set-value width 0.1)))))))
|
||||
|
||||
(defn smile-button []
|
||||
(let [command? (subscribe [:command?])
|
||||
buttons-scale (anim/create-value (if @command? 1 0))
|
||||
(let [command? (subscribe [:command?])
|
||||
buttons-scale (anim/create-value (if @command? 1 0))
|
||||
container-width (anim/create-value (if @command? 0.1 56))
|
||||
context {:command? command?
|
||||
:val buttons-scale
|
||||
:width container-width}
|
||||
on-update (smile-animation-logic context)]
|
||||
context {:command? command?
|
||||
:val buttons-scale
|
||||
:width container-width}
|
||||
on-update (smile-animation-logic context)]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
on-update
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
(def request-message-icon-scale-delay 600)
|
||||
|
||||
(defn set-chat-command [msg-id command]
|
||||
(dispatch [:set-response-chat-command msg-id (:command command)]))
|
||||
(dispatch [:set-response-chat-command msg-id (keyword (:name command))]))
|
||||
|
||||
(defn label [{:keys [command]}]
|
||||
(->> (name command)
|
||||
|
@ -56,18 +56,19 @@
|
|||
:reagent-render
|
||||
(fn [msg-id command]
|
||||
@to-scale
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(reset! loop? false)
|
||||
(set-chat-command msg-id command))
|
||||
:style st/command-request-image-touchable
|
||||
:accessibility-label (label command)}
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(reset! loop? false)
|
||||
(set-chat-command msg-id command))
|
||||
:style st/command-request-image-touchable}
|
||||
;:accessibility-label (label command)
|
||||
|
||||
[animated-view {:style (st/command-request-image-view command scale-anim-val)}
|
||||
[image {:source (:request-icon command)
|
||||
[image {:source {:uri (:icon command)}
|
||||
:style st/command-request-image}]]])})))
|
||||
|
||||
(defn message-content-command-request
|
||||
[{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands-atom (subscribe [:get-commands])]
|
||||
(let [commands-atom (subscribe [:get-responses])]
|
||||
(fn [{:keys [msg-id content from incoming-group]}]
|
||||
(let [commands @commands-atom
|
||||
{:keys [command content]} (parse-command-request commands content)]
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
text-input
|
||||
touchable-highlight]]
|
||||
[status-im.components.drag-drop :as drag]
|
||||
[status-im.chat.views.response-suggestions :refer [response-suggestions-view]]
|
||||
[status-im.chat.styles.response :as st]
|
||||
[status-im.chat.styles.message-input :refer [input-height]]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.components.react :as react]))
|
||||
|
||||
|
@ -51,7 +49,6 @@
|
|||
;; todo maybe it is better to use margin-top instead height
|
||||
;; it is not obvious
|
||||
to-value (- (prop w) @kb-height (.-moveY gesture))]
|
||||
(println to-value )
|
||||
(anim/start
|
||||
(anim/spring response-height {:toValue to-value}))))))
|
||||
|
||||
|
@ -88,7 +85,9 @@
|
|||
(defn container-animation-logic [{:keys [to-value val]}]
|
||||
(fn [_]
|
||||
(let [to-value @to-value]
|
||||
(anim/start (anim/spring val {:toValue to-value})))))
|
||||
(anim/start (anim/spring val {:toValue to-value
|
||||
:tension 50
|
||||
:friction 10})))))
|
||||
|
||||
(defn container [response-height & children]
|
||||
(let [;; todo to-response-height, cur-response-height must be specific
|
||||
|
@ -109,9 +108,18 @@
|
|||
(into [animated-view {:style (st/response-view response-height)}]
|
||||
children))})))
|
||||
|
||||
(defview placeholder []
|
||||
[suggestions [:get-content-suggestions]]
|
||||
(when (seq suggestions)
|
||||
[view st/input-placeholder]))
|
||||
|
||||
(defview response-suggestions-view []
|
||||
[suggestions [:get-content-suggestions]]
|
||||
(when (seq suggestions) suggestions))
|
||||
|
||||
(defn response-view []
|
||||
(let [response-height (anim/create-value 0)]
|
||||
[container response-height
|
||||
[request-info response-height]
|
||||
[response-suggestions-view]
|
||||
[view st/input-placeholder]]))
|
||||
[placeholder]]))
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
(ns status-im.chat.views.response-suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
icon
|
||||
text
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
[status-im.chat.styles.response-suggestions :as st]
|
||||
[status-im.utils.listview :refer [to-datasource]]))
|
||||
|
||||
(defn set-command-content [content]
|
||||
(dispatch [:set-chat-command-content content]))
|
||||
|
||||
(defn header-list-item [{:keys [header]}]
|
||||
[view st/header-container
|
||||
[text {:style st/header-text} header]])
|
||||
|
||||
(defn suggestion-list-item [{:keys [value description]}]
|
||||
[touchable-highlight {:onPress #(set-command-content value)}
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[text {:style st/value-text} value]
|
||||
[text {:style st/description-text} description]]]])
|
||||
|
||||
(defn render-row [row _ _]
|
||||
(list-item (if (:header row)
|
||||
[header-list-item row]
|
||||
[suggestion-list-item row])))
|
||||
|
||||
(defview response-suggestions-view []
|
||||
[suggestions [:get-content-suggestions]]
|
||||
(when (seq suggestions)
|
||||
[view st/suggestions-container
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:keyboardShouldPersistTaps true
|
||||
:renderRow render-row}]]))
|
|
@ -1,9 +1,9 @@
|
|||
(ns status-im.chat.views.staged-command
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
image
|
||||
text
|
||||
touchable-highlight]]
|
||||
image
|
||||
text
|
||||
touchable-highlight]]
|
||||
[status-im.resources :as res]
|
||||
[status-im.chat.styles.input :as st]))
|
||||
|
||||
|
@ -16,13 +16,12 @@
|
|||
[view st/staged-command-background
|
||||
[view st/staged-command-info-container
|
||||
[view (st/staged-command-text-container command)
|
||||
[text {:style st/staged-command-text} (:text command)]]
|
||||
[text {:style st/staged-command-text} (str "!" (:name command))]]
|
||||
[touchable-highlight {:style st/staged-command-cancel
|
||||
:onPress #(cancel-command-input staged-command)}
|
||||
[image {:source res/icon-close-gray
|
||||
:style st/staged-command-cancel-icon}]]]
|
||||
[text {:style st/staged-command-content}
|
||||
;; TODO isn't smart
|
||||
(if (= (:command command) :keypair-password)
|
||||
"******"
|
||||
(:content staged-command))]]]))
|
||||
(if-let [preview (:preview staged-command)]
|
||||
preview
|
||||
[text {:style st/staged-command-content}
|
||||
(:content staged-command)])]]))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
(ns status-im.chat.views.suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
|
@ -13,35 +14,35 @@
|
|||
(dispatch [:set-chat-command command]))
|
||||
|
||||
(defn suggestion-list-item
|
||||
[{:keys [description command]
|
||||
label :text
|
||||
:as suggestion}]
|
||||
[touchable-highlight
|
||||
{:onPress #(set-command-input (keyword command))}
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[view (st/suggestion-background suggestion)
|
||||
[text {:style st/suggestion-text} label]]
|
||||
[text {:style st/value-text} label]
|
||||
[text {:style st/description-text} description]]]])
|
||||
[[command {:keys [description]
|
||||
name :name
|
||||
:as suggestion}]]
|
||||
(let [label (str "!" name)]
|
||||
[touchable-highlight
|
||||
{:onPress #(set-command-input command)}
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[view (st/suggestion-background suggestion)
|
||||
[text {:style st/suggestion-text} label]]
|
||||
[text {:style st/value-text} label]
|
||||
[text {:style st/description-text} description]]]]))
|
||||
|
||||
(defn render-row [row _ _]
|
||||
(list-item [suggestion-list-item row]))
|
||||
|
||||
(defn suggestions-view []
|
||||
(let [suggestions-atom (subscribe [:get-suggestions])]
|
||||
(fn []
|
||||
(let [suggestions @suggestions-atom]
|
||||
(when (seq suggestions)
|
||||
[view st/container
|
||||
[touchable-highlight {:style st/drag-down-touchable
|
||||
:onPress (fn []
|
||||
;; TODO hide suggestions?
|
||||
)}
|
||||
[view
|
||||
[icon :drag_down st/drag-down-icon]]]
|
||||
[view (st/suggestions-container (count suggestions))
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps true
|
||||
:renderRow render-row}]]])))))
|
||||
|
||||
(defview suggestions-view []
|
||||
[suggestions [:get-suggestions]]
|
||||
(when (seq suggestions)
|
||||
[view st/container
|
||||
[touchable-highlight {:style st/drag-down-touchable
|
||||
:onPress (fn []
|
||||
;; TODO hide suggestions?
|
||||
)}
|
||||
[view
|
||||
[icon :drag_down st/drag-down-icon]]]
|
||||
[view (st/suggestions-container (count suggestions))
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps true
|
||||
:renderRow render-row}]]]))
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
(ns status-im.commands.handlers.jail
|
||||
(:require [re-frame.core :refer [register-handler after dispatch subscribe
|
||||
trim-v debug]]
|
||||
[status-im.utils.handlers :as u]
|
||||
[status-im.utils.utils :refer [http-get toast]]
|
||||
[status-im.components.jail :as j]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
[status-im.commands.utils :refer [generate-hiccup reg-handler]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(defn init-render-command!
|
||||
[_ [chat-id command message-id data]]
|
||||
(j/call chat-id [command :render] data
|
||||
#(dispatch [::render-command chat-id message-id %])))
|
||||
|
||||
(defn render-command
|
||||
[db [chat-id message-id markup]]
|
||||
(let [hiccup (generate-hiccup markup)]
|
||||
(assoc-in db [:rendered-commands chat-id message-id] hiccup)))
|
||||
|
||||
(def console-events
|
||||
{:save-password #(dispatch [:save-password %])
|
||||
:sign-up #(dispatch [:sign-up %])
|
||||
:confirm-sign-up #(dispatch [:sign-up-confirm %])})
|
||||
|
||||
(def regular-events {})
|
||||
|
||||
(defn command-hadler!
|
||||
[_ [{:keys [to]} {:keys [result]} ]]
|
||||
(when result
|
||||
(let [{:keys [event params]} result
|
||||
events (if (= "console" to)
|
||||
(merge regular-events console-events)
|
||||
regular-events)]
|
||||
(when-let [handler (events (keyword event))]
|
||||
(apply handler params)))))
|
||||
|
||||
(defn suggestions-handler!
|
||||
[db [{:keys [chat-id]} {:keys [result]} ]]
|
||||
(assoc-in db [:suggestions chat-id] (generate-hiccup result)))
|
||||
|
||||
(defn suggestions-events-handler!
|
||||
[db [[n data]]]
|
||||
(case (keyword n)
|
||||
:set-value (dispatch [:set-chat-command-content data])
|
||||
;; todo show error?
|
||||
nil))
|
||||
|
||||
(defn command-preview
|
||||
[db [chat-id {:keys [result]}]]
|
||||
(if result
|
||||
(let [path [:chats chat-id :staged-commands]
|
||||
commands-cnt (count (get-in db path))]
|
||||
;; 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-string (str result)))
|
||||
db))
|
||||
|
||||
(defn print-error-message! [message]
|
||||
(fn [_ params]
|
||||
(when (:error (last params))
|
||||
(toast (s/join "\n" [message params]))
|
||||
(println message params))))
|
||||
|
||||
(reg-handler :init-render-command! init-render-command!)
|
||||
(reg-handler ::render-command render-command)
|
||||
|
||||
(reg-handler :command-handler!
|
||||
(after (print-error-message! "Error on command handling"))
|
||||
(u/side-effect! command-hadler!))
|
||||
(reg-handler :suggestions-handler
|
||||
[(after #(dispatch [:animate-show-response]))
|
||||
(after (print-error-message! "Error on param suggestions"))]
|
||||
suggestions-handler!)
|
||||
(reg-handler :suggestions-event! (u/side-effect! suggestions-events-handler!))
|
||||
(reg-handler :command-preview
|
||||
(after (print-error-message! "Error on command preview"))
|
||||
command-preview)
|
|
@ -0,0 +1,103 @@
|
|||
(ns status-im.commands.handlers.loading
|
||||
(:require-macros [status-im.utils.slurp :refer [slurp]])
|
||||
(:require [re-frame.core :refer [register-handler after dispatch subscribe
|
||||
trim-v debug]]
|
||||
[status-im.utils.handlers :as u]
|
||||
[status-im.utils.utils :refer [http-get toast]]
|
||||
[clojure.string :as s]
|
||||
[status-im.persistence.realm :as realm]
|
||||
[status-im.components.jail :as j]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
[status-im.commands.utils :refer [reg-handler]]))
|
||||
|
||||
(def commands-js "commands.js")
|
||||
|
||||
(defn load-commands!
|
||||
[_ [identity]]
|
||||
(dispatch [::fetch-commands! identity])
|
||||
;; todo uncomment
|
||||
#_(if-let [{:keys [file]} (realm/get-one-by-field :commands :chat-id
|
||||
identity)]
|
||||
(dispatch [::parse-commands! identity file])
|
||||
(dispatch [::fetch-commands! identity])))
|
||||
|
||||
(defn fetch-commands!
|
||||
[db [identity]]
|
||||
(when-let [url (:dapp-url (get-in db [:chats identity]))]
|
||||
(if (= "console" identity)
|
||||
(dispatch [::validate-hash identity (slurp "resources/commands.js")])
|
||||
(http-get (s/join "/" [url commands-js])
|
||||
#(dispatch [::validate-hash identity %])
|
||||
#(dispatch [::loading-failed! identity ::file-was-not-found])))))
|
||||
|
||||
(defn dispatch-loaded!
|
||||
[db [identity file]]
|
||||
(if (::valid-hash db)
|
||||
(dispatch [::parse-commands! identity file])
|
||||
(dispatch [::loading-failed! identity ::wrong-hash])))
|
||||
|
||||
(defn get-hash-by-identity
|
||||
[db identity]
|
||||
(get-in db [:chats identity :dapp-hash]))
|
||||
|
||||
(defn get-hash-by-file
|
||||
[file]
|
||||
;; todo tbd hashing algorithm
|
||||
(hash file))
|
||||
|
||||
(defn parse-commands! [_ [identity file]]
|
||||
(j/parse identity file
|
||||
(fn [result]
|
||||
(let [{:keys [error result]} (json->clj result)]
|
||||
(if error
|
||||
(dispatch [::loading-failed! identity ::error-in-jail error])
|
||||
(dispatch [::add-commands identity file result]))))))
|
||||
|
||||
(defn validate-hash
|
||||
[db [identity file]]
|
||||
(let [valid? true
|
||||
;; todo check
|
||||
#_(= (get-hash-by-identity db identity)
|
||||
(get-hash-by-file file))]
|
||||
(assoc db ::valid-hash valid?)))
|
||||
|
||||
(defn mark-as [as coll]
|
||||
(->> coll
|
||||
(map (fn [[k v]] [k (assoc v :type as)]))
|
||||
(into {})))
|
||||
|
||||
(defn add-commands
|
||||
[db [id _ {:keys [commands responses]}]]
|
||||
(-> db
|
||||
(update-in [:chats id :commands] merge (mark-as :command commands))
|
||||
(update-in [:chats id :responses] merge (mark-as :response responses))))
|
||||
|
||||
(defn save-commands-js!
|
||||
[_ [id file]]
|
||||
(realm/create-object :commands {:chat-id id :file file}))
|
||||
|
||||
(defn loading-failed!
|
||||
[db [id reason details]]
|
||||
(let [url (get-in db [:chats id :dapp-url])]
|
||||
(let [m (s/join "\n" ["commands.js loading failed"
|
||||
url
|
||||
id
|
||||
(name reason)
|
||||
details])]
|
||||
(toast m)
|
||||
(println m))))
|
||||
|
||||
(reg-handler :load-commands! (u/side-effect! load-commands!))
|
||||
(reg-handler ::fetch-commands! (u/side-effect! fetch-commands!))
|
||||
|
||||
(reg-handler ::validate-hash
|
||||
(after dispatch-loaded!)
|
||||
validate-hash)
|
||||
|
||||
(reg-handler ::parse-commands! (u/side-effect! parse-commands!))
|
||||
|
||||
(reg-handler ::add-commands
|
||||
(after save-commands-js!)
|
||||
add-commands)
|
||||
|
||||
(reg-handler ::loading-failed! (u/side-effect! loading-failed!))
|
|
@ -0,0 +1,47 @@
|
|||
(ns status-im.commands.utils
|
||||
(:require [clojure.set :as set]
|
||||
[clojure.walk :as w]
|
||||
[status-im.components.react :refer [text scroll-view view
|
||||
image touchable-highlight]]
|
||||
[re-frame.core :refer [register-handler dispatch trim-v debug]]))
|
||||
|
||||
(defn json->clj [json]
|
||||
(if (= json "undefined")
|
||||
nil
|
||||
(js->clj (.parse js/JSON json) :keywordize-keys true)))
|
||||
|
||||
(def elements
|
||||
{:text text
|
||||
:view view
|
||||
:scroll-view scroll-view
|
||||
:image image
|
||||
:touchable touchable-highlight})
|
||||
|
||||
(defn get-element [n]
|
||||
(elements (keyword (.toLowerCase n))))
|
||||
|
||||
(def events #{:onPress})
|
||||
|
||||
(defn wrap-event [event]
|
||||
#(dispatch [:suggestions-event! event]))
|
||||
|
||||
(defn check-events [m]
|
||||
(let [ks (set (keys m))
|
||||
evs (set/intersection ks events)]
|
||||
(reduce #(update %1 %2 wrap-event) m evs)))
|
||||
|
||||
(defn generate-hiccup [markup]
|
||||
;; todo implement validation
|
||||
(w/prewalk
|
||||
(fn [el]
|
||||
(if (and (vector? el) (string? (first el)))
|
||||
(-> el
|
||||
(update 0 get-element)
|
||||
(update 1 check-events))
|
||||
el))
|
||||
markup))
|
||||
|
||||
(defn reg-handler
|
||||
([name handler] (reg-handler name nil handler))
|
||||
([name middleware handler]
|
||||
(register-handler name [#_debug trim-v middleware] handler)))
|
|
@ -0,0 +1,27 @@
|
|||
(ns status-im.components.jail
|
||||
(:require-macros [status-im.utils.slurp :refer [slurp]])
|
||||
(:require [status-im.components.react :as r]
|
||||
[status-im.utils.types :as t]))
|
||||
|
||||
(def status-js (slurp "resources/status.js"))
|
||||
|
||||
(def jail
|
||||
(when (exists? (.-NativeModules r/react))
|
||||
(.-Jail (.-NativeModules r/react))))
|
||||
|
||||
(when jail
|
||||
(.init jail status-js))
|
||||
|
||||
(defn parse [chat-id file callback]
|
||||
(.parse jail chat-id file callback))
|
||||
|
||||
(defn cljs->json [data]
|
||||
(.stringify js/JSON (clj->js data)))
|
||||
|
||||
(defn call [chat-id path params callback]
|
||||
(println :call chat-id (cljs->json path) (cljs->json params))
|
||||
(let [cb (fn [r]
|
||||
(let [r' (t/json->clj r)]
|
||||
(println r')
|
||||
(callback r')))]
|
||||
(.call jail chat-id (cljs->json path) (cljs->json params) cb)))
|
|
@ -96,7 +96,6 @@
|
|||
(remove #(identities (:whisper-identity %)))
|
||||
(map #(vector (:whisper-identity %) %))
|
||||
(into {}))]
|
||||
(println new-contacts')
|
||||
(-> db
|
||||
(update :contacts merge new-contacts')
|
||||
(assoc :new-contacts (vals new-contacts')))))
|
||||
|
|
|
@ -5,18 +5,19 @@
|
|||
[status-im.db :refer [app-db schema]]
|
||||
[status-im.persistence.simple-kv-store :as kv]
|
||||
[status-im.protocol.state.storage :as storage]
|
||||
[status-im.models.commands :refer [set-commands]]
|
||||
[status-im.chat.suggestions :refer [load-commands]]
|
||||
[status-im.utils.logging :as log]
|
||||
[status-im.utils.crypt :refer [gen-random-bytes]]
|
||||
[status-im.utils.handlers :as u]
|
||||
status-im.chat.handlers
|
||||
status-im.chat.handlers.animation
|
||||
status-im.group-settings.handlers
|
||||
status-im.navigation.handlers
|
||||
status-im.contacts.handlers
|
||||
status-im.discovery.handlers
|
||||
status-im.new-group.handlers
|
||||
status-im.participants.handlers
|
||||
status-im.commands.handlers.loading
|
||||
status-im.commands.handlers.jail
|
||||
status-im.qr-scanner.handlers
|
||||
status-im.protocol.handlers))
|
||||
|
||||
|
@ -80,17 +81,6 @@
|
|||
(fn [_ _]
|
||||
(log/debug "crypt initialized"))))
|
||||
|
||||
(register-handler :load-commands
|
||||
(u/side-effect!
|
||||
(fn [_ [action]]
|
||||
(log/debug action)
|
||||
(load-commands))))
|
||||
|
||||
(register-handler :set-commands
|
||||
(fn [db [action commands]]
|
||||
(log/debug action commands)
|
||||
(set-commands db commands)))
|
||||
|
||||
;; -- User data --------------------------------------------------------------
|
||||
(register-handler :load-user-phone-number
|
||||
(fn [db [_]]
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
(defn get-content-suggestions [command text]
|
||||
(or (when command
|
||||
(when-let [command-suggestions ((:command command) suggestions)]
|
||||
(when-let [command-suggestions ((keyword (:name command)) suggestions)]
|
||||
(filterv (fn [s]
|
||||
(or (:header s)
|
||||
(and (.startsWith (:value s) (or text ""))
|
||||
|
|
|
@ -7,72 +7,14 @@
|
|||
[status-im.components.styles :refer [color-blue color-dark-mint]]
|
||||
[status-im.i18n :refer [label]]))
|
||||
|
||||
;; todo delete
|
||||
(def commands [{:command :money
|
||||
:text "!money"
|
||||
:description (label :t/money-command-description)
|
||||
:color color-dark-mint
|
||||
:request-icon {:uri "icon_lock_white"}
|
||||
:icon {:uri "icon_lock_gray"}
|
||||
:suggestion true}
|
||||
{:command :location
|
||||
:text "!location"
|
||||
:description (label :t/location-command-description)
|
||||
:color "#9a5dcf"
|
||||
:suggestion true}
|
||||
{:command :phone
|
||||
:text "!phone"
|
||||
:description (label :t/phone-command-description)
|
||||
:color color-dark-mint
|
||||
:request-text (label :t/phone-request-text)
|
||||
:suggestion true
|
||||
:handler #(dispatch [:sign-up %])}
|
||||
{:command :confirmation-code
|
||||
:text "!confirmationCode"
|
||||
:description (label :t/confirmation-code-command-description)
|
||||
:request-text (label :t/confirmation-code-request-text)
|
||||
:color color-blue
|
||||
:request-icon {:uri "icon_lock_white"}
|
||||
:icon {:uri "icon_lock_gray"}
|
||||
:suggestion true
|
||||
:handler #(dispatch [:sign-up-confirm %])}
|
||||
{:command :send
|
||||
:text "!send"
|
||||
:description (label :t/send-command-description)
|
||||
:color "#9a5dcf"
|
||||
:suggestion true}
|
||||
{:command :request
|
||||
:text "!request"
|
||||
:description (label :t/request-command-description)
|
||||
:color "#48ba30"
|
||||
:suggestion true}
|
||||
{:command :keypair-password
|
||||
:text "!keypair-password"
|
||||
:description (label :t/keypair-password-command-description)
|
||||
:color color-blue
|
||||
:request-icon {:uri "icon_lock_white"}
|
||||
:icon {:uri "icon_lock_gray"}
|
||||
:suggestion false
|
||||
:handler #(dispatch [:save-password %])}
|
||||
{:command :help
|
||||
:text "!help"
|
||||
:description (label :t/help-command-description)
|
||||
:color "#9a5dcf"
|
||||
:suggestion true}])
|
||||
(defn get-commands [{:keys [current-chat-id] :as db}]
|
||||
(or (get-in db [:chats current-chat-id :commands]) {}))
|
||||
|
||||
(defn get-commands [db]
|
||||
;; todo: temp. must be '(get db :commands)'
|
||||
;; (get db :commands)
|
||||
commands)
|
||||
|
||||
(defn set-commands [db commands]
|
||||
(assoc db :commands commands))
|
||||
|
||||
;; todo delete
|
||||
(def suggestions (filterv :suggestion commands))
|
||||
|
||||
(defn get-command [db command-key]
|
||||
(first (filter #(= command-key (:command %)) (get-commands db))))
|
||||
(defn get-command [{:keys [current-chat-id] :as db} command-key]
|
||||
((or (->> (get-in db [:chats current-chat-id])
|
||||
((juxt :commands :responses))
|
||||
(apply merge))
|
||||
{}) command-key))
|
||||
|
||||
(defn find-command [commands command-key]
|
||||
(first (filter #(= command-key (:command %)) commands)))
|
||||
|
@ -130,7 +72,7 @@
|
|||
#(assoc % msg-id handler)))
|
||||
|
||||
(defn parse-command-msg-content [commands content]
|
||||
(update content :command #(find-command commands (keyword %))))
|
||||
(update content :command #((keyword %) commands)))
|
||||
|
||||
(defn parse-command-request [commands content]
|
||||
(update content :command #(find-command commands (keyword %))))
|
||||
(update content :command #((keyword %) commands)))
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
[status-im.utils.logging :as log]
|
||||
[clojure.string :refer [join split]]
|
||||
[clojure.walk :refer [stringify-keys keywordize-keys]]
|
||||
[status-im.constants :as c]))
|
||||
[status-im.constants :as c]
|
||||
[status-im.commands.utils :refer [generate-hiccup]]))
|
||||
|
||||
(defn- map-to-str
|
||||
[m]
|
||||
|
@ -20,7 +21,8 @@
|
|||
{:outgoing false
|
||||
:to nil
|
||||
:same-author false
|
||||
:same-direction false})
|
||||
:same-direction false
|
||||
:preview nil})
|
||||
|
||||
(defn save-message
|
||||
;; todo remove chat-id parameter
|
||||
|
@ -45,6 +47,24 @@
|
|||
#{c/content-type-command c/content-type-command-request}
|
||||
type))
|
||||
|
||||
<<<<<<< HEAD
|
||||
(defn get-messages [chat-id]
|
||||
(->> (-> (r/get-by-field :msgs :chat-id chat-id)
|
||||
(r/sorted :timestamp :desc)
|
||||
(r/collection->map))
|
||||
(into '())
|
||||
;; todo why reverse?
|
||||
reverse
|
||||
(map (fn [{:keys [content-type preview] :as message}]
|
||||
(if (command-type? content-type)
|
||||
(-> message
|
||||
(update :content str-to-map)
|
||||
(assoc :rendered-preview (when preview
|
||||
(generate-hiccup
|
||||
(read-string preview))))
|
||||
(dissoc :preview))
|
||||
message)))))
|
||||
=======
|
||||
(defn get-messages
|
||||
([chat-id] (get-messages chat-id 0))
|
||||
([chat-id from]
|
||||
|
@ -58,6 +78,7 @@
|
|||
(if (command-type? content-type)
|
||||
(update message :content str-to-map)
|
||||
message))))))
|
||||
>>>>>>> develop
|
||||
|
||||
(defn update-message! [{:keys [msg-id] :as msg}]
|
||||
(log/debug "update-message!" msg)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.navigation.handlers
|
||||
(:require [re-frame.core :refer [register-handler dispatch debug enrich
|
||||
after]]))
|
||||
(:require [re-frame.core :refer [register-handler dispatch debug enrich after]]))
|
||||
|
||||
(defn push-view [db view-id]
|
||||
(-> db
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns status-im.persistence.realm
|
||||
(:require [cljs.reader :refer [read-string]]
|
||||
[status-im.components.styles :refer [default-chat-color]]
|
||||
[status-im.utils.logging :as log]
|
||||
[status-im.utils.types :refer [to-string]]
|
||||
[status-im.utils.utils :as u])
|
||||
(:refer-clojure :exclude [exists?]))
|
||||
|
@ -34,7 +33,9 @@
|
|||
:delivery-status {:type "string"
|
||||
:optional true}
|
||||
:same-author "bool"
|
||||
:same-direction "bool"}}
|
||||
:same-direction "bool"
|
||||
:preview {:type :string
|
||||
:optional true}}}
|
||||
{:name :chat-contact
|
||||
:properties {:identity "string"
|
||||
:is-in-chat {:type "bool"
|
||||
|
@ -51,7 +52,15 @@
|
|||
:timestamp "int"
|
||||
:contacts {:type "list"
|
||||
:objectType "chat-contact"}
|
||||
:dapp-url {:type :string
|
||||
:optional true}
|
||||
:dapp-hash {:type :int
|
||||
:optional true}
|
||||
:last-msg-id "string"}}
|
||||
{:name :commands
|
||||
:primaryKey :chat-id
|
||||
:properties {:chat-id "string"
|
||||
:file "string"}}
|
||||
{:name :tag
|
||||
:primaryKey :name
|
||||
:properties {:name "string"
|
||||
|
@ -94,6 +103,10 @@
|
|||
([schema-name obj update?]
|
||||
(.create realm (to-string schema-name) (clj->js obj) update?)))
|
||||
|
||||
(defn create-object
|
||||
[schema-name obj]
|
||||
(write (fn [] (create schema-name obj true))))
|
||||
|
||||
(defmulti to-query (fn [schema-name operator field value]
|
||||
operator))
|
||||
|
||||
|
@ -158,3 +171,6 @@
|
|||
(defn collection->map [collection]
|
||||
(-> (.map collection (fn [object _ _] object))
|
||||
(js->clj :keywordize-keys true)))
|
||||
|
||||
(defn get-one-by-field [schema-name field value]
|
||||
(single-cljs (get-by-field schema-name field value)))
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
(ns status-im.utils.slurp
|
||||
(:refer-clojure :exclude [slurp]))
|
||||
|
||||
(defmacro slurp [file]
|
||||
(clojure.core/slurp file))
|
|
@ -11,5 +11,6 @@
|
|||
(defn clj->json [data]
|
||||
(.stringify js/JSON (clj->js data)))
|
||||
|
||||
(defn json->clj [data]
|
||||
(js->clj (.parse js/JSON data) :keywordize-keys true))
|
||||
(defn json->clj [json]
|
||||
(when-not (= json "undefined")
|
||||
(js->clj (.parse js/JSON json) :keywordize-keys true)))
|
||||
|
|
|
@ -41,10 +41,8 @@
|
|||
(toast (str error))))))))
|
||||
|
||||
(defn http-get
|
||||
([action on-success on-error]
|
||||
(-> (.fetch js/window
|
||||
(str const/server-address action)
|
||||
(clj->js {:method "GET"}))
|
||||
([url on-success on-error]
|
||||
(-> (.fetch js/window url (clj->js {:method "GET"}))
|
||||
(.then (fn [response]
|
||||
(log response)
|
||||
(.text response)))
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
(ns status-im.test.commands.handlers
|
||||
(:require [cljs.test :refer-macros [deftest is]]
|
||||
[status-im.commands.handlers.loading :as h]))
|
||||
|
||||
(deftest test-validate-hash
|
||||
(let [file "some-js"
|
||||
db (-> {}
|
||||
(assoc-in [:chats :user :dapp-hash] -731917028)
|
||||
(assoc-in [:chats :user2 :dapp-hash] 123))]
|
||||
(is (::h/valid-hash (h/validate-hash db [:user file])))
|
||||
(is (not (::h/valid-hash (h/validate-hash db [:user2 file]))))
|
||||
(is (not (::h/valid-hash (h/validate-hash db [:user3 file]))))))
|
||||
|
||||
(deftest test-add-commands
|
||||
(let [obj {:commands {:test {:name "name"
|
||||
:description "desc"}}
|
||||
:responses {:test-r {:name "r"
|
||||
:description "desc-r"}}}
|
||||
db (h/add-commands {} [:user nil obj])]
|
||||
(is (= obj (select-keys (get-in db [:chats :user]) [:commands :responses])))))
|
|
@ -1,5 +1,7 @@
|
|||
(ns status-im.test.runner
|
||||
(:require [doo.runner :refer-macros [doo-tests]]
|
||||
[status-im.test.handlers]))
|
||||
[status-im.test.handlers]
|
||||
[status-im.test.commands.handlers]))
|
||||
|
||||
(doo-tests 'status-im.test.handlers)
|
||||
(doo-tests 'status-im.test.handlers
|
||||
'status-im.test.commands.handlers)
|
||||
|
|
Loading…
Reference in New Issue