split console bot into separate files
bots dir slurp-bot macro split commands.js into browse, mailman and wallet bot-url & loading of default bots command schema command-parameter schema global-command in default_commands @browse command in all chats load global command from jail optimize applications startup Conflicts: bots/wallet/translations.js resources/console.js resources/dapp.js resources/default_contacts.json resources/status.js resources/wallet.js src/status_im/accounts/screen.cljs src/status_im/chat/constants.cljs src/status_im/chat/handlers.cljs src/status_im/chat/handlers/commands.cljs src/status_im/chat/handlers/send_message.cljs src/status_im/chat/subs.cljs src/status_im/chat/suggestions.cljs src/status_im/chat/views/command.cljs src/status_im/chat/views/suggestions.cljs src/status_im/commands/handlers/jail.cljs src/status_im/commands/handlers/loading.cljs src/status_im/contacts/handlers.cljs src/status_im/data_store/realm/schemas/account/core.cljs src/status_im/data_store/realm/schemas/account/v5/core.cljs src/status_im/models/commands.cljs src/status_im/utils/js_resources.cljs
This commit is contained in:
parent
4e932d9ae8
commit
239a0cbfe6
|
@ -0,0 +1,36 @@
|
|||
function browseSuggestions(params, context) {
|
||||
var url;
|
||||
|
||||
if (context["dapp-url"]) {
|
||||
url = context["dapp-url"];
|
||||
}
|
||||
|
||||
if (params.url && params.url !== "undefined" && params.url != "") {
|
||||
url = params.url;
|
||||
if (!/^[a-zA-Z-_]+:/.test(url)) {
|
||||
url = 'http://' + url;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Browser",
|
||||
dynamicTitle: true,
|
||||
markup: status.components.bridgedWebView(url)
|
||||
};
|
||||
}
|
||||
|
||||
status.command({
|
||||
name: "global",
|
||||
title: I18n.t('browse_title'),
|
||||
registeredOnly: true,
|
||||
description: I18n.t('browse_description'),
|
||||
color: "#ffa500",
|
||||
fullscreen: true,
|
||||
suggestionsTrigger: 'on-send',
|
||||
params: [{
|
||||
name: "url",
|
||||
type: status.types.TEXT,
|
||||
placeholder: "URL"
|
||||
}],
|
||||
onSend: browseSuggestions
|
||||
});
|
|
@ -0,0 +1,134 @@
|
|||
I18n.translations = {
|
||||
en: {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Launch the browser'
|
||||
},
|
||||
ru: {
|
||||
browse_title: 'Браузер',
|
||||
browse_description: 'Запуск браузера'
|
||||
},
|
||||
af: {
|
||||
browse_title: 'Webblaaier',
|
||||
browse_description: 'Begin die webblaaier'
|
||||
},
|
||||
ar: {
|
||||
browse_title: 'المتصفح',
|
||||
browse_description: 'تشغيل المتصفح'
|
||||
},
|
||||
'zh-hant': {
|
||||
browse_title: '流覽器',
|
||||
browse_description: '啟動流覽器'
|
||||
},
|
||||
'zh-hans': {
|
||||
browse_title: '浏览器',
|
||||
browse_description: '启动浏览器'
|
||||
},
|
||||
'zh-yue': {
|
||||
browse_title: '瀏覽器',
|
||||
browse_description: '啟動瀏覽器'
|
||||
},
|
||||
'zh-wuu': {
|
||||
browse_title: '浏览器',
|
||||
browse_description: '启动浏览器'
|
||||
},
|
||||
nl: {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Start de browser'
|
||||
},
|
||||
fr: {
|
||||
browse_title: 'Navigateur',
|
||||
browse_description: 'Lancer le navigateur'
|
||||
},
|
||||
de: {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Browser starten'
|
||||
},
|
||||
hi: {
|
||||
browse_title: 'ब्राउज़र',
|
||||
browse_description: 'ब्राउज़र लॉन्च करें'
|
||||
},
|
||||
hu: {
|
||||
browse_title: 'Böngésző',
|
||||
browse_description: 'Böngésző indítása'
|
||||
},
|
||||
it: {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Lancia il browser'
|
||||
},
|
||||
ja: {
|
||||
browse_title: 'ブラウザ',
|
||||
browse_description: 'ブラウザを起動'
|
||||
},
|
||||
ko: {
|
||||
browse_title: '브라우저',
|
||||
browse_description: '브라우저 시작하기'
|
||||
},
|
||||
pl: {
|
||||
browse_title: 'Przeglądarka',
|
||||
browse_description: 'Uruchom przeglądarkę'
|
||||
},
|
||||
'pt-br': {
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Abrir o navegador'
|
||||
},
|
||||
'pt-pt': {
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Abrir o navegador'
|
||||
},
|
||||
ro: {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Lansare browser'
|
||||
},
|
||||
sl: {
|
||||
browse_title: 'Brskalnik',
|
||||
browse_description: 'Zaženi brskalnik'
|
||||
},
|
||||
es: {
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Iniciar el navegador'
|
||||
},
|
||||
'es-ar': {
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Iniciar navegador'
|
||||
},
|
||||
sw: {
|
||||
send_title: 'Tuma ETH',
|
||||
send_description: 'Tuma malipo'
|
||||
},
|
||||
sv: {
|
||||
browse_title: 'Webbläsare',
|
||||
browse_description: 'Starta webbläsaren'
|
||||
},
|
||||
'fr-ch': {
|
||||
browse_title: 'Navigateur',
|
||||
browse_description: 'Lancer le navigateur'
|
||||
},
|
||||
'de-ch': {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Starte den Browser'
|
||||
},
|
||||
'it-ch': {
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Avvia il browser'
|
||||
},
|
||||
th: {
|
||||
browse_title: 'เบราว์เซอร์',
|
||||
browse_description: 'เปิดเบราว์เซอร์'
|
||||
},
|
||||
tr: {
|
||||
browse_title: 'Tarayıcı',
|
||||
browse_description: 'Tarayıcıyı başlat'
|
||||
},
|
||||
uk: {
|
||||
browse_title: 'Браузер',
|
||||
browse_description: 'Запустити браузер'
|
||||
},
|
||||
ur: {
|
||||
browse_title: 'براؤزر',
|
||||
browse_description: 'براؤزر کھولیں'
|
||||
},
|
||||
vi: {
|
||||
browse_title: 'Trình duyệt',
|
||||
browse_description: 'Mở trình duyệt'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,752 @@
|
|||
function jsSuggestionsContainerStyle(suggestionsCount) {
|
||||
return {
|
||||
marginVertical: 1,
|
||||
marginHorizontal: 0,
|
||||
keyboardShouldPersistTaps: "always",
|
||||
//height: Math.min(150, (56 * suggestionsCount)),
|
||||
backgroundColor: "white",
|
||||
borderRadius: 5,
|
||||
keyboardShouldPersistTaps: "always"
|
||||
};
|
||||
}
|
||||
|
||||
var jsSuggestionContainerStyle = {
|
||||
paddingLeft: 16,
|
||||
backgroundColor: "white"
|
||||
};
|
||||
|
||||
var jsSubContainerStyle = {
|
||||
//height: 56,
|
||||
paddingTop: 9,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#0000001f"
|
||||
};
|
||||
|
||||
var jsValueStyle = {
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#000000de"
|
||||
};
|
||||
|
||||
var jsBoldValueStyle = {
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#000000de",
|
||||
fontWeight: "bold"
|
||||
};
|
||||
|
||||
var jsDescriptionStyle = {
|
||||
marginTop: 1.5,
|
||||
paddingBottom: 9,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "#838c93de"
|
||||
};
|
||||
|
||||
var messages = [];
|
||||
|
||||
|
||||
console = (function (old) {
|
||||
return {
|
||||
log: function (text) {
|
||||
old.log(text);
|
||||
var message = {
|
||||
type: 'log',
|
||||
message: JSON.stringify(text)
|
||||
};
|
||||
messages.push(message);
|
||||
context.messages.push(message);
|
||||
},
|
||||
info: function (text) {
|
||||
old.info(text);
|
||||
context.messages.push({
|
||||
type: 'info',
|
||||
message: JSON.stringify(text)
|
||||
});
|
||||
},
|
||||
warn: function (text) {
|
||||
old.warn(text);
|
||||
context.messages.push({
|
||||
type: 'warn',
|
||||
message: JSON.stringify(text)
|
||||
});
|
||||
},
|
||||
error: function (text) {
|
||||
old.error(text);
|
||||
context.messages.push({
|
||||
type: 'error',
|
||||
message: JSON.stringify(text)
|
||||
});
|
||||
}
|
||||
};
|
||||
}(console));
|
||||
|
||||
|
||||
if (!String.prototype.startsWith) {
|
||||
String.prototype.startsWith = function (searchString, position) {
|
||||
position = position || 0;
|
||||
return this.substr(position, searchString.length) === searchString;
|
||||
};
|
||||
}
|
||||
|
||||
function matchSubString(array, string) {
|
||||
var matched = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var item = array[i];
|
||||
if (item.toLowerCase().startsWith(string.toLowerCase())) {
|
||||
matched.push(item);
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
function cleanCode(code) {
|
||||
// remove comments
|
||||
var commentsRegex = /\/\*.+?\*\/|\/\/.*/g;
|
||||
code = code.replace(commentsRegex, "");
|
||||
// replace string literals
|
||||
var literalsRegex = /\"(?:\\\\\"|[^\"])*?\"/g;
|
||||
code = code.replace(literalsRegex, '""');
|
||||
var literalsRegex = /\'(?:\\\\\'|[^\'])*?\'/g;
|
||||
code = code.replace(literalsRegex, '""');
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
function createObjectSuggestion(name, docInfo, code, parameterNumber) {
|
||||
var title = name;
|
||||
if (docInfo.args) {
|
||||
title += "(";
|
||||
for (var i = 0; i < docInfo.args.length; i++) {
|
||||
var argument = docInfo.args[i];
|
||||
var argumentText = (i > 0 ? ", " : "") + (parameterNumber === i ? "*" + argument.name + "*" : argument.name);
|
||||
if (argument.optional) {
|
||||
argumentText = "[" + argumentText + "]";
|
||||
}
|
||||
title += argumentText;
|
||||
}
|
||||
title += ")";
|
||||
}
|
||||
if (!docInfo.desc) {
|
||||
name += ".";
|
||||
} else if (docInfo.args) {
|
||||
name += "(";
|
||||
if (docInfo.args.length == 0) {
|
||||
name += ")";
|
||||
}
|
||||
}
|
||||
var suggestion = {
|
||||
title: title,
|
||||
desc: docInfo.desc
|
||||
};
|
||||
|
||||
if (code != null) {
|
||||
suggestion.pressValue = code + name;
|
||||
}
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
var lastMessage = null;
|
||||
|
||||
function getLastForm(code) {
|
||||
var codeLength = code.length;
|
||||
var form = '';
|
||||
var level = 0;
|
||||
var index = codeLength - 1;
|
||||
while (index >= 0) {
|
||||
var char = code[index];
|
||||
if (level == 0 && (char == '(' || char == ',')) {
|
||||
break;
|
||||
}
|
||||
if (char == ')') {
|
||||
level--;
|
||||
}
|
||||
if (char == '(') {
|
||||
level++;
|
||||
}
|
||||
form = char + form;
|
||||
index--;
|
||||
}
|
||||
return form;
|
||||
}
|
||||
|
||||
function getLastLevel(code) {
|
||||
var codeLength = code.length;
|
||||
var form = '';
|
||||
var index = codeLength - 1;
|
||||
var nested = false;
|
||||
var level = 0;
|
||||
while (index >= 0) {
|
||||
var char = code[index];
|
||||
if (char == ')') {
|
||||
level--;
|
||||
nested = true;
|
||||
}
|
||||
if (char == '(') {
|
||||
level++;
|
||||
if (level == 0) {
|
||||
nested = false;
|
||||
}
|
||||
if (level <= 0) {
|
||||
form = "argument" + form;
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((level == 1 && char == ',') || level == 2) {
|
||||
break;
|
||||
}
|
||||
if (!nested || level > 0) {
|
||||
form = char + form;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
if (form.indexOf("(") < 0) {
|
||||
var parts = form.split(',');
|
||||
form = parts[parts.length - 1];
|
||||
}
|
||||
return form;
|
||||
}
|
||||
|
||||
function getPartialSuggestions(doc, fullCode, code) {
|
||||
var suggestions = [];
|
||||
var functionParts = code.split("(");
|
||||
var objectParts = code.split(/[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/);
|
||||
|
||||
var index = 0;
|
||||
var suggestedFunction = '';
|
||||
while (index < objectParts.length) {
|
||||
var part = objectParts[index];
|
||||
if (part != "desc" && part != "args" && doc[part] != null) {
|
||||
doc = doc[part];
|
||||
suggestedFunction += part + '.';
|
||||
index++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
suggestedFunction = suggestedFunction.substring(0, suggestedFunction.length - 1)
|
||||
if (functionParts.length == 1) {
|
||||
// object suggestions
|
||||
if (index > objectParts.length - 1) {
|
||||
var suggestion = objectParts[objectParts.length - 1];
|
||||
suggestions.push(createObjectSuggestion(suggestion, doc, fullCode.substring(0, fullCode.length - suggestion.length)));
|
||||
} else if (index === objectParts.length - 1) {
|
||||
var lastPart = objectParts[index];
|
||||
var keys = Object.keys(doc);
|
||||
var matches = matchSubString(keys, lastPart);
|
||||
|
||||
for (var i = 0; i < matches.length; i++) {
|
||||
var suggestion = matches[i];
|
||||
if (suggestion == "desc" || suggestion == "args") {
|
||||
continue;
|
||||
}
|
||||
var docInfo = doc[suggestion];
|
||||
if (docInfo != null) {
|
||||
suggestions.push(createObjectSuggestion(suggestion, docInfo, fullCode.substring(0, fullCode.length - lastPart.length)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (functionParts.length == 2) {
|
||||
// parameter suggestions
|
||||
var parameters = functionParts[1].split(",");
|
||||
if (doc.args && parameters.length <= doc.args.length && parameters[parameters.length - 1].indexOf(")") < 0) {
|
||||
var paramInfo = doc.args[parameters.length - 1];
|
||||
var docInfo = doc;
|
||||
docInfo.desc = paramInfo.name + ": " + paramInfo.desc;
|
||||
suggestions.push(createObjectSuggestion(suggestedFunction, docInfo, null, parameters.length - 1));
|
||||
}
|
||||
}
|
||||
console.log(suggestions);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
function getJsSuggestions(code, context) {
|
||||
var suggestions = [];
|
||||
var doc = DOC_MAP;
|
||||
// TODO: what's /c / doing there ???
|
||||
console.log(code);
|
||||
if (!code || code == "" || code == "c ") {
|
||||
code = "";
|
||||
console.log("Last message: " + context.data);
|
||||
if (context.data != null) {
|
||||
suggestions.push({
|
||||
title: 'Last command used:',
|
||||
desc: context.data,
|
||||
pressValue: context.data
|
||||
});
|
||||
}
|
||||
var keys = Object.keys(doc);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var suggestion = keys[i];
|
||||
var docInfo = doc[suggestion];
|
||||
if (docInfo != null) {
|
||||
suggestions.push(createObjectSuggestion(suggestion, docInfo, ""));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: what's /c / doing there ???
|
||||
if (code.startsWith("c ")) {
|
||||
code = code.substring(2);
|
||||
}
|
||||
if (context.data != null &&
|
||||
(typeof context.data === 'string' || context.data instanceof String) &&
|
||||
context.data.startsWith(code)) {
|
||||
suggestions.unshift({
|
||||
title: 'Last command used:',
|
||||
desc: context.data,
|
||||
pressValue: context.data
|
||||
});
|
||||
}
|
||||
var originalCode = code;
|
||||
code = cleanCode(code);
|
||||
var levelCode = getLastLevel(code);
|
||||
var code = getLastForm(levelCode);
|
||||
if (levelCode != code) {
|
||||
suggestions = getPartialSuggestions(doc, originalCode, levelCode);
|
||||
}
|
||||
|
||||
console.log("Final code: " + code);
|
||||
console.log("Level code: " + levelCode);
|
||||
suggestions = suggestions.concat(getPartialSuggestions(doc, originalCode, code));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
function createMarkupText(text) {
|
||||
var parts = [];
|
||||
var index = 0;
|
||||
var currentText = '';
|
||||
var isBold = false;
|
||||
while (index < text.length) {
|
||||
var char = text[index];
|
||||
if (char == '*') {
|
||||
if (currentText != '') {
|
||||
parts.push(
|
||||
status.components.text(
|
||||
{style: isBold ? jsBoldValueStyle : jsValueStyle},
|
||||
currentText
|
||||
)
|
||||
);
|
||||
currentText = '';
|
||||
}
|
||||
isBold = !isBold;
|
||||
} else {
|
||||
currentText += char;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (currentText != '') {
|
||||
parts.push(
|
||||
status.components.text(
|
||||
{style: isBold ? jsBoldValueStyle : jsValueStyle},
|
||||
currentText
|
||||
)
|
||||
);
|
||||
}
|
||||
console.log(parts);
|
||||
return parts;
|
||||
}
|
||||
|
||||
function jsSuggestions(params, context) {
|
||||
var suggestions = getJsSuggestions(params.code, context);
|
||||
var sugestionsMarkup = [];
|
||||
|
||||
for (var i = 0; i < suggestions.length; i++) {
|
||||
var suggestion = suggestions[i];
|
||||
|
||||
if (suggestion.title.indexOf('*') >= 0) {
|
||||
suggestion.title = createMarkupText(suggestion.title);
|
||||
}
|
||||
var suggestionMarkup = status.components.view(jsSuggestionContainerStyle,
|
||||
[status.components.view(jsSubContainerStyle,
|
||||
[
|
||||
status.components.text({style: jsValueStyle},
|
||||
suggestion.title),
|
||||
status.components.text({style: jsDescriptionStyle},
|
||||
suggestion.desc)
|
||||
])]);
|
||||
if (suggestion.pressValue) {
|
||||
suggestionMarkup = status.components.touchable({
|
||||
onPress: [status.events.SET_VALUE, suggestion.pressValue]
|
||||
},
|
||||
suggestionMarkup);
|
||||
}
|
||||
sugestionsMarkup.push(suggestionMarkup);
|
||||
}
|
||||
|
||||
if (sugestionsMarkup.length > 0) {
|
||||
var view = status.components.scrollView(jsSuggestionsContainerStyle(sugestionsMarkup.length),
|
||||
sugestionsMarkup
|
||||
);
|
||||
return {markup: view};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function jsHandler(params, context) {
|
||||
var result = {
|
||||
err: null,
|
||||
data: null,
|
||||
messages: []
|
||||
};
|
||||
messages = [];
|
||||
try {
|
||||
result.data = JSON.stringify(eval(params.code));
|
||||
localStorage.set(params.code);
|
||||
} catch (e) {
|
||||
result.err = e;
|
||||
}
|
||||
|
||||
result.messages = messages;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function suggestionsContainerStyle(suggestionsCount) {
|
||||
return {
|
||||
marginVertical: 1,
|
||||
marginHorizontal: 0,
|
||||
keyboardShouldPersistTaps: "always",
|
||||
height: Math.min(150, (56 * suggestionsCount)),
|
||||
backgroundColor: "white",
|
||||
borderRadius: 5,
|
||||
flexGrow: 1
|
||||
};
|
||||
}
|
||||
|
||||
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, context) {
|
||||
var ph, suggestions;
|
||||
if (!params.phone || params.phone == "") {
|
||||
ph = context.suggestions;
|
||||
} else {
|
||||
ph = context.suggestions.filter(function (phone) {
|
||||
return startsWith(phone.number, params.phone);
|
||||
});
|
||||
}
|
||||
|
||||
if (ph.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
suggestions = ph.map(function (phone) {
|
||||
return status.components.touchable(
|
||||
{onPress: [status.events.SET_COMMAND_ARGUMENT, [0, phone.number]]},
|
||||
status.components.view(suggestionContainerStyle,
|
||||
[status.components.view(suggestionSubContainerStyle,
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
phone.number
|
||||
),
|
||||
status.components.text(
|
||||
{style: descriptionStyle},
|
||||
phone.description
|
||||
)
|
||||
])])
|
||||
);
|
||||
});
|
||||
|
||||
var view = status.components.scrollView(
|
||||
suggestionsContainerStyle(ph.length),
|
||||
suggestions
|
||||
);
|
||||
|
||||
return {markup: view};
|
||||
}
|
||||
|
||||
var phoneConfig = {
|
||||
name: "phone",
|
||||
registeredOnly: true,
|
||||
icon: "phone_white",
|
||||
color: "#5bb2a2",
|
||||
title: I18n.t('phone_title'),
|
||||
description: I18n.t('phone_description'),
|
||||
sequentialParams: true,
|
||||
validator: function (params) {
|
||||
return {
|
||||
validationHandler: "phone",
|
||||
parameters: [params.phone]
|
||||
};
|
||||
},
|
||||
params: [{
|
||||
name: "phone",
|
||||
type: status.types.PHONE,
|
||||
suggestions: phoneSuggestions,
|
||||
placeholder: I18n.t('phone_placeholder')
|
||||
}]
|
||||
};
|
||||
status.response(phoneConfig);
|
||||
status.command(phoneConfig);
|
||||
|
||||
var faucets = [
|
||||
/*{
|
||||
name: "Ethereum Ropsten Faucet",
|
||||
url: "http://faucet.ropsten.be:3001"
|
||||
},*/
|
||||
{
|
||||
name: "Status Testnet Faucet",
|
||||
url: "http://46.101.129.137:3001",
|
||||
}
|
||||
];
|
||||
|
||||
function faucetSuggestions(params) {
|
||||
var suggestions = faucets.map(function (entry) {
|
||||
return status.components.touchable(
|
||||
{onPress: [status.events.SET_COMMAND_ARGUMENT, [0, entry.url]]},
|
||||
status.components.view(
|
||||
suggestionContainerStyle,
|
||||
[status.components.view(
|
||||
suggestionSubContainerStyle,
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
entry.name
|
||||
),
|
||||
status.components.text(
|
||||
{style: descriptionStyle},
|
||||
entry.url
|
||||
)
|
||||
]
|
||||
)]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
var view = status.components.scrollView(
|
||||
suggestionsContainerStyle(faucets.length),
|
||||
suggestions
|
||||
);
|
||||
|
||||
return {markup: view};
|
||||
}
|
||||
|
||||
status.command({
|
||||
name: "faucet",
|
||||
title: I18n.t('faucet_title'),
|
||||
description: I18n.t('faucet_description'),
|
||||
color: "#7099e6",
|
||||
registeredOnly: true,
|
||||
params: [{
|
||||
name: "url",
|
||||
type: status.types.TEXT,
|
||||
suggestions: faucetSuggestions,
|
||||
placeholder: I18n.t('faucet_placeholder')
|
||||
}],
|
||||
preview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
params.url
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('faucet_title') + ": " + params.url
|
||||
)
|
||||
};
|
||||
},
|
||||
validator: function (params, context) {
|
||||
var f = faucets.map(function (entry) {
|
||||
return entry.url;
|
||||
});
|
||||
|
||||
if (f.indexOf(params.url) == -1) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('faucet_incorrect_title'),
|
||||
I18n.t('faucet_incorrect_description')
|
||||
);
|
||||
|
||||
return {markup: error};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function debugSuggestions(params) {
|
||||
var suggestions = ["On", "Off"].map(function (entry) {
|
||||
return status.components.touchable(
|
||||
{onPress: [status.events.SET_COMMAND_ARGUMENT, [0, entry]]},
|
||||
status.components.view(
|
||||
suggestionContainerStyle,
|
||||
[status.components.view(
|
||||
suggestionSubContainerStyle,
|
||||
[
|
||||
status.components.text(
|
||||
{style: valueStyle},
|
||||
entry
|
||||
)
|
||||
]
|
||||
)]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
var view = status.components.scrollView(
|
||||
suggestionsContainerStyle(faucets.length),
|
||||
suggestions
|
||||
);
|
||||
|
||||
return {markup: view};
|
||||
}
|
||||
|
||||
status.command({
|
||||
name: "debug",
|
||||
title: I18n.t('debug_mode_title'),
|
||||
description: I18n.t('debug_mode_description'),
|
||||
color: "#7099e6",
|
||||
registeredOnly: true,
|
||||
params: [{
|
||||
name: "mode",
|
||||
suggestions: debugSuggestions,
|
||||
type: status.types.TEXT
|
||||
}],
|
||||
preview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('debug_mode_title') + ": " + params.mode
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('debug_mode_title') + ": " + params.mode
|
||||
)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// status.command({
|
||||
// name: "help",
|
||||
// title: "Help",
|
||||
// description: "Request help from Console",
|
||||
// color: "#7099e6",
|
||||
// params: [{
|
||||
// name: "query",
|
||||
// type: status.types.TEXT
|
||||
// }]
|
||||
// });
|
||||
|
||||
status.response({
|
||||
name: "confirmation-code",
|
||||
color: "#7099e6",
|
||||
description: I18n.t('confirm_description'),
|
||||
sequentialParams: true,
|
||||
params: [{
|
||||
name: "code",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
validator: function (params) {
|
||||
if (!/^[\d]{4}$/.test(params.code)) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('confirm_validation_title'),
|
||||
I18n.t('confirm_validation_description')
|
||||
);
|
||||
|
||||
return {markup: error};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
status.response({
|
||||
name: "password",
|
||||
color: "#7099e6",
|
||||
description: I18n.t('password_description'),
|
||||
icon: "lock_white",
|
||||
sequentialParams: true,
|
||||
params: [
|
||||
{
|
||||
name: "password",
|
||||
type: status.types.PASSWORD,
|
||||
placeholder: I18n.t('password_placeholder'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
name: "password-confirmation",
|
||||
type: status.types.PASSWORD,
|
||||
placeholder: I18n.t('password_placeholder2'),
|
||||
hidden: true
|
||||
}
|
||||
],
|
||||
validator: function (params, context) {
|
||||
if (!params.hasOwnProperty("password-confirmation") || params["password-confirmation"].length === 0) {
|
||||
if (params.password === null || params.password.length < 6) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('password_validation_title'),
|
||||
I18n.t('password_error')
|
||||
);
|
||||
return {markup: error};
|
||||
}
|
||||
} else {
|
||||
if (params.password !== params["password-confirmation"]) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('password_validation_title'),
|
||||
I18n.t('password_error1')
|
||||
);
|
||||
return {markup: error};
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
preview: function (params, context) {
|
||||
var style = {
|
||||
marginTop: 5,
|
||||
marginHorizontal: 0,
|
||||
fontSize: 14,
|
||||
color: "black"
|
||||
};
|
||||
|
||||
if (context.platform == "ios") {
|
||||
style.fontSize = 8;
|
||||
style.marginTop = 10;
|
||||
style.marginBottom = 2;
|
||||
style.letterSpacing = 1;
|
||||
}
|
||||
|
||||
return {markup: status.components.text({style: style}, "●●●●●●●●●●")};
|
||||
}
|
||||
});
|
||||
|
||||
status.registerFunction("message-suggestions", function (params, context) {
|
||||
return jsSuggestions({code: params.message}, context);
|
||||
});
|
||||
|
||||
status.registerFunction("message-handler", function (params, context) {
|
||||
return jsHandler({code: params.message}, context);
|
||||
});
|
|
@ -0,0 +1,572 @@
|
|||
I18n.translations = {
|
||||
en: {
|
||||
phone_title: 'Send Phone Number',
|
||||
phone_description: 'Find friends using your number',
|
||||
phone_placeholder: 'Phone number',
|
||||
|
||||
confirm_description: 'Confirmation code',
|
||||
confirm_validation_title: 'Confirmation code',
|
||||
confirm_validation_description: 'Wrong format',
|
||||
|
||||
password_description: 'Password',
|
||||
password_placeholder: 'Type your password',
|
||||
password_placeholder2: 'Please re-enter password to confirm',
|
||||
password_error: 'Password should be not less then 6 symbols.',
|
||||
password_error1: 'Password confirmation doesn\'t match password.',
|
||||
password_validation_title: 'Password',
|
||||
|
||||
faucet_incorrect_title: 'Incorrect faucet',
|
||||
faucet_incorrect_description: 'Please, select a one from the list',
|
||||
|
||||
debug_mode_title: 'Debug mode',
|
||||
debug_mode_description: 'Starts/stops a debug mode',
|
||||
|
||||
faucet_title: 'Faucet',
|
||||
faucet_description: 'Get some ETH',
|
||||
faucet_placeholder: 'Faucet URL'
|
||||
},
|
||||
ru: {
|
||||
phone_title: 'Отправить номер телефона',
|
||||
phone_description: 'Найти друзей, используя ваш номер',
|
||||
phone_placeholder: 'Номер телефона',
|
||||
|
||||
confirm_description: 'Код подтверждения',
|
||||
confirm_validation_title: 'Код подтверждения',
|
||||
confirm_validation_description: 'Неверный формат',
|
||||
|
||||
password_description: 'Пароль',
|
||||
password_placeholder: 'Введите свой пароль',
|
||||
password_placeholder2: 'Повторно введите пароль для подтверждения',
|
||||
password_error: 'Пароль должен содержать не менее 6 символов',
|
||||
password_error1: 'Подтверждение пароля не совпадает с паролем',
|
||||
password_validation_title: 'Пароль'
|
||||
|
||||
},
|
||||
af: {
|
||||
phone_title: 'Stuur telefoonnommer',
|
||||
phone_description: 'Vind vriende deur jou nommer te gebruik',
|
||||
phone_placeholder: 'Telefoonnommer',
|
||||
|
||||
confirm_description: 'Bevestigingskode',
|
||||
confirm_validation_title: 'Bevestigingskode',
|
||||
confirm_validation_description: 'Verkeerde formaat',
|
||||
|
||||
password_description: 'Wagwoord',
|
||||
password_placeholder: 'Tik jou wagwoord in',
|
||||
password_placeholder2: 'Tik asseblief weer jou wagwoord in om te bevestig',
|
||||
password_error: 'Wagwoord mag nie minder as 6 simbole wees nie.',
|
||||
password_error1: 'Wagwoordbevestiging is nie dieselfde as wagwoord nie.',
|
||||
password_validation_title: 'Wagwoord'
|
||||
|
||||
},
|
||||
ar: {
|
||||
phone_title: 'أرسل رقم الهاتف',
|
||||
phone_description: 'ابحث عن الأصدقاء باستخدام رقمك',
|
||||
phone_placeholder: 'رقم الهاتف',
|
||||
|
||||
confirm_description: 'رمز التأكيد',
|
||||
confirm_validation_title: 'رمز التأكيد',
|
||||
confirm_validation_description: 'صيغة خاطئة',
|
||||
|
||||
password_description: 'كلمة المرور',
|
||||
password_placeholder: 'اكتب كلمة المرور الخاصة بك',
|
||||
password_placeholder2: 'الرجاء إعادة إدخال كلمة المرور للتأكيد',
|
||||
password_error: 'ينبغي أن لا تقل كلمة المرور عن 6 رموز.',
|
||||
password_error1: 'لا يتوافق تأكيد كلمة المرور مع كلمة المرور.',
|
||||
password_validation_title: 'كلمة المرور'
|
||||
|
||||
},
|
||||
'zh-hant': {
|
||||
phone_title: '發送手機號碼',
|
||||
phone_description: '使用您的號碼發現好友',
|
||||
phone_placeholder: '手機號碼',
|
||||
|
||||
confirm_description: '確認碼',
|
||||
confirm_validation_title: '確認碼',
|
||||
confirm_validation_description: '格式錯誤',
|
||||
|
||||
password_description: '密碼',
|
||||
password_placeholder: '鍵入您的密碼',
|
||||
password_placeholder2: '重新鍵入您的密碼',
|
||||
password_error: '密碼不得短於6個字元。',
|
||||
password_error1: '確認密碼與鍵入的密碼不一致。',
|
||||
password_validation_title: '密碼'
|
||||
|
||||
},
|
||||
'zh-hans': {
|
||||
phone_title: '发送电话号码',
|
||||
phone_description: '用你的号码来查找朋友',
|
||||
phone_placeholder: '电话号码',
|
||||
|
||||
confirm_description: '确认码',
|
||||
confirm_validation_title: '确认码',
|
||||
confirm_validation_description: '格式错误',
|
||||
|
||||
password_description: '密码',
|
||||
password_placeholder: '输入密码',
|
||||
password_placeholder2: '请重新输入密码以确认',
|
||||
password_error: '密码应不少于6个字符。',
|
||||
password_error1: '密码确认信息与密码不匹配。',
|
||||
password_validation_title: '密码'
|
||||
|
||||
},
|
||||
'zh-yue': {
|
||||
phone_title: '發送電話號碼',
|
||||
phone_description: '使用本電話號碼查找好友',
|
||||
phone_placeholder: '電話號碼',
|
||||
|
||||
confirm_description: '驗證碼',
|
||||
confirm_validation_title: '驗證碼',
|
||||
confirm_validation_description: '格式錯誤',
|
||||
|
||||
password_description: '密碼',
|
||||
password_placeholder: '輸入密碼',
|
||||
password_placeholder2: '請重新輸入密碼確認',
|
||||
password_error: '密碼不能短於6個字符.',
|
||||
password_error1: '確認密碼與輸入密碼不符.',
|
||||
password_validation_title: '密碼'
|
||||
|
||||
},
|
||||
'zh-wuu': {
|
||||
phone_title: '发送电话号码',
|
||||
phone_description: '用您的号码查找朋友',
|
||||
phone_placeholder: '电话号码',
|
||||
|
||||
confirm_description: '确认码',
|
||||
confirm_validation_title: '确认码',
|
||||
confirm_validation_description: '错误格式',
|
||||
|
||||
password_description: '密码',
|
||||
password_placeholder: '输入密码',
|
||||
password_placeholder2: '请重新输入密码确认',
|
||||
password_error: '密码应不小于6个字符。',
|
||||
password_error1: '密码确认不匹配。',
|
||||
password_validation_title: '密码'
|
||||
|
||||
},
|
||||
nl: {
|
||||
phone_title: 'Stuur telefoonnummer',
|
||||
phone_description: 'Zoek vrienden met behulp van je nummer',
|
||||
phone_placeholder: 'Telefoonnummer',
|
||||
|
||||
confirm_description: 'Bevestigingscode',
|
||||
confirm_validation_title: 'Bevestigingscode',
|
||||
confirm_validation_description: 'Verkeerd format',
|
||||
|
||||
password_description: 'Wachtwoord',
|
||||
password_placeholder: 'Typ je wachtwoord',
|
||||
password_placeholder2: 'Voer je wachtwoord opnieuw in om te bevestigen',
|
||||
password_error: 'Wachtwoord moet minstens 6 tekens hebben.',
|
||||
password_error1: 'Wachtwoordbevestiging komt niet overeen met wachtwoord.',
|
||||
password_validation_title: 'Wachtwoord'
|
||||
|
||||
},
|
||||
fr: {
|
||||
phone_title: 'Envoyer le numéro de téléphone',
|
||||
phone_description: 'Trouver des amis en utilisant votre numéro',
|
||||
phone_placeholder: 'Numéro de téléphone',
|
||||
|
||||
confirm_description: 'Code de confirmation',
|
||||
confirm_validation_title: 'Code de confirmation',
|
||||
confirm_validation_description: 'Format incorrect',
|
||||
|
||||
password_description: 'Mot de passe',
|
||||
password_placeholder: 'Tapez votre mot de passe',
|
||||
password_placeholder2: 'Veuillez retapez votre mot de passe pour le confirmer',
|
||||
password_error: 'Le mot de passe doit contenir 6 symboles au minimum.',
|
||||
password_error1: 'Le mot de passe de confirmation ne correspond pas au mot de passe.',
|
||||
password_validation_title: 'Mot de passe'
|
||||
|
||||
},
|
||||
de: {
|
||||
phone_title: 'Telefonnummer absenden',
|
||||
phone_description: 'Freunde mit Ihrer Nummer finden',
|
||||
phone_placeholder: 'Telefonnummer',
|
||||
|
||||
confirm_description: 'Bestätigungscode',
|
||||
confirm_validation_title: 'Bestätigungscode',
|
||||
confirm_validation_description: 'Falsches Format',
|
||||
|
||||
password_description: 'Passwort',
|
||||
password_placeholder: 'Geben Sie Ihr Passwort ein',
|
||||
password_placeholder2: 'Bitte geben Sie das Passwort zur Bestätigung erneut ein',
|
||||
password_error: 'Das Passwort sollte nicht weniger als 6 Stellen beinhalten',
|
||||
password_error1: 'Die Passwortbestätigung stimmt nicht mit dem Passwort überein',
|
||||
password_validation_title: 'Passwort',
|
||||
|
||||
},
|
||||
hi: {
|
||||
phone_title: 'फ़ोन नंबर भेजें',
|
||||
phone_description: 'अपने नंबर का उपयोग करके दोस्त ढूंढें',
|
||||
phone_placeholder: 'फ़ोन नंबर',
|
||||
|
||||
confirm_description: 'पुष्टि कोड',
|
||||
confirm_validation_title: 'पुष्टि कोड',
|
||||
confirm_validation_description: 'गलत प्रारूप',
|
||||
|
||||
password_description: 'पासवर्ड',
|
||||
password_placeholder: 'अपना पासवर्ड टाइप करें',
|
||||
password_placeholder2: 'पुष्टि करने के लिए फिर से पासवर्ड दर्ज करें',
|
||||
password_error: 'पासवर्ड 6 प्रतीकों से कम का नहीं होना चाहिए।',
|
||||
password_error1: 'पासवर्ड पुष्टि पासवर्ड मेल नहीं खाता है।',
|
||||
password_validation_title: 'पासवर्ड'
|
||||
|
||||
},
|
||||
hu: {
|
||||
phone_title: 'Telefonszám küldése',
|
||||
phone_description: 'Ismerősök megkeresése telefonszám alapján',
|
||||
phone_placeholder: 'Telefonszám',
|
||||
|
||||
confirm_description: 'Megerősítési kód',
|
||||
confirm_validation_title: 'Megerősítési kód',
|
||||
confirm_validation_description: 'Rossz formátum',
|
||||
|
||||
password_description: 'Jelszó',
|
||||
password_placeholder: 'Add meg a jelszavad',
|
||||
password_placeholder2: 'A megerősítéshez kérjük, add meg újra a jelszavad',
|
||||
password_error: 'A jelszó nem lehet hosszabb 6 szimbólumnál.',
|
||||
password_error1: 'A megerősített jelszó nem egyezik a jelszóval.',
|
||||
password_validation_title: 'Jelszó'
|
||||
|
||||
},
|
||||
it: {
|
||||
phone_title: 'Invia numero di telefono',
|
||||
phone_description: 'Trova gli amici che usano il tuo numero',
|
||||
phone_placeholder: 'Numero di telefono',
|
||||
|
||||
confirm_description: 'Codice di conferma',
|
||||
confirm_validation_title: 'Codice di conferma',
|
||||
confirm_validation_description: 'Formato errato',
|
||||
|
||||
password_description: 'Password',
|
||||
password_placeholder: 'Digita la tua password',
|
||||
password_placeholder2: 'Reinserisci la password per confermare',
|
||||
password_error: 'La password deve contenere almeno 6 caratteri.',
|
||||
password_error1: 'Conferma password\ la password non corrisponde.',
|
||||
password_validation_title: 'Password'
|
||||
|
||||
},
|
||||
ja: {
|
||||
phone_title: '電話番号を送信',
|
||||
phone_description: 'あなたの番号を使用している友人を検索',
|
||||
phone_placeholder: '携帯電話番号',
|
||||
|
||||
confirm_description: '確認コード',
|
||||
confirm_validation_title: '確認コード',
|
||||
confirm_validation_description: '間違った形式',
|
||||
|
||||
password_description: 'パスワード',
|
||||
password_placeholder: 'パスワードを入力してください',
|
||||
password_placeholder2: '確認のためにパスワードを再入力してください',
|
||||
password_error: 'パスワードは6文字以下でなければなりません.',
|
||||
password_error1: 'パスワードの確認がパスワードと一致しません。',
|
||||
password_validation_title: 'パスワード'
|
||||
|
||||
},
|
||||
ko: {
|
||||
phone_title: '전화번호 보내기',
|
||||
phone_description: '내 번호를 사용하여 친구 찾기',
|
||||
phone_placeholder: '전화번호',
|
||||
|
||||
confirm_description: '확인 코드',
|
||||
confirm_validation_title: '확인 코드',
|
||||
confirm_validation_description: '잘못된 형식',
|
||||
|
||||
password_description: '비밀번호',
|
||||
password_placeholder: '비밀번호를 입력하세요',
|
||||
password_placeholder2: '확인을 위해 비밀번호를 다시 입력해 주세요',
|
||||
password_error: '비밀번호는 6자 이상이어야 합니다.',
|
||||
password_error1: '확인용 비밀번호가 원래 비밀번호와 일치하지 않습니다.',
|
||||
password_validation_title: '비밀번호'
|
||||
|
||||
},
|
||||
pl: {
|
||||
phone_title: 'Wyślij numer telefonu',
|
||||
phone_description: 'Znajdź znajomych, używając swojego numeru',
|
||||
phone_placeholder: 'Numer telefonu',
|
||||
|
||||
confirm_description: 'Kod potwierdzający',
|
||||
confirm_validation_title: 'Kod potwierdzający',
|
||||
confirm_validation_description: 'Nieprawidłowy format',
|
||||
|
||||
password_description: 'Hasło',
|
||||
password_placeholder: 'Wpisz swoje hasło',
|
||||
password_placeholder2: 'Wprowadź ponownie hasło, aby potwierdzić',
|
||||
password_error: 'Hasło powinno zawierać co najmniej 6 symboli.',
|
||||
password_error1: 'Wprowadzone i potwierdzone hasła nie są takie same.',
|
||||
password_validation_title: 'Hasło'
|
||||
|
||||
},
|
||||
'pt-br': {
|
||||
phone_title: 'Enviar número de telefone',
|
||||
phone_description: 'Encontrar amigos por meio do seu número',
|
||||
phone_placeholder: 'Número de telefone',
|
||||
|
||||
confirm_description: 'Código de confirmação',
|
||||
confirm_validation_title: 'Código de confirmação',
|
||||
confirm_validation_description: 'Formato incorreto',
|
||||
|
||||
password_description: 'Senha',
|
||||
password_placeholder: 'Digite sua senha',
|
||||
password_placeholder2: 'Por favor, digite a senha novamente para confirmar',
|
||||
password_error: 'A senha deve ter no mínimo 6 símbolos.',
|
||||
password_error1: 'A confirmação da senha é diferente da senha.',
|
||||
password_validation_title: 'Senha'
|
||||
|
||||
},
|
||||
'pt-pt': {
|
||||
phone_title: 'Enviar o Número de Telefone',
|
||||
phone_description: 'Encontrar amigos que utilizem o seu número',
|
||||
phone_placeholder: 'Número de telefone',
|
||||
|
||||
confirm_description: 'Código de confirmação',
|
||||
confirm_validation_title: 'Código de confirmação',
|
||||
confirm_validation_description: 'Formato errado',
|
||||
|
||||
password_description: 'Palavra-passe',
|
||||
password_placeholder: 'Digite a sua palavra-passe',
|
||||
password_placeholder2: 'Por favor, volte a digitar a palavra-passe para confirmar',
|
||||
password_error: 'A palavra-passe não deve ter menos de 6 símbolos.',
|
||||
password_error1: 'A confirmação da palavra-passe não coincide com a palavra-passe.',
|
||||
password_validation_title: 'Palavra-passe'
|
||||
|
||||
},
|
||||
ro: {
|
||||
phone_title: 'Trimite numărul de telefon',
|
||||
phone_description: 'Găsește prieteni folosindu-ți numărul de telefon',
|
||||
phone_placeholder: 'Număr de telefon',
|
||||
|
||||
confirm_description: 'Cod de confirmare',
|
||||
confirm_validation_title: 'Cod de confirmare',
|
||||
confirm_validation_description: 'Format greșit',
|
||||
|
||||
password_description: 'Parolă',
|
||||
password_placeholder: 'Tastează parola',
|
||||
password_placeholder2: 'Te rugăm să re-introduci parola pentru a confirma',
|
||||
password_error: 'Parola trebuie să aibă cel puțin 6 simboluri.',
|
||||
password_error1: 'Parola confirmată nu este aceeași cu parola introdusă.',
|
||||
password_validation_title: 'Parolă'
|
||||
|
||||
},
|
||||
sl: {
|
||||
phone_title: 'Pošlji telefonsko številko',
|
||||
phone_description: 'Iskanje prijateljev z uporabo tvoje telefonske številke',
|
||||
phone_placeholder: 'Telefonska številka',
|
||||
|
||||
confirm_description: 'Potrditvena koda',
|
||||
confirm_validation_title: 'Potrditvena koda',
|
||||
confirm_validation_description: 'Neveljaven format',
|
||||
|
||||
password_description: 'Geslo',
|
||||
password_placeholder: 'Vnesi svoje geslo',
|
||||
password_placeholder2: 'Prosimo, ponovno vnesi geslo za potrditev',
|
||||
password_error: 'Geslo mora vsebovati vsaj 6 simbolov.',
|
||||
password_error1: 'Potrditev gesla se ne ujema z geslom.',
|
||||
password_validation_title: 'Geslo'
|
||||
|
||||
},
|
||||
es: {
|
||||
phone_title: 'Enviar número de teléfono',
|
||||
phone_description: 'Encontrar amigos que estén utilizando tu número',
|
||||
phone_placeholder: 'Número de teléfono',
|
||||
|
||||
confirm_description: 'Código de confirmación',
|
||||
confirm_validation_title: 'Código de confirmación',
|
||||
confirm_validation_description: 'Formato erróneo',
|
||||
|
||||
password_description: 'Contraseña',
|
||||
password_placeholder: 'Escribe tu contraseña',
|
||||
password_placeholder2: 'Por favor, vuelve a escribir la contraseña para confirmar',
|
||||
password_error: 'La contraseña no debe ser inferior a 6 símbolos.',
|
||||
password_error1: 'La confirmación de contraseña no coincide con la contraseña.',
|
||||
password_validation_title: 'Contraseña'
|
||||
|
||||
},
|
||||
'es-ar': {
|
||||
phone_title: 'Envia un número telefónico',
|
||||
phone_description: 'Encuentra amigos utilizando tu número',
|
||||
phone_placeholder: 'Número telefónico',
|
||||
|
||||
confirm_description: 'Código de confirmación',
|
||||
confirm_validation_title: 'Código de confirmación',
|
||||
confirm_validation_description: 'Formato incorrecto',
|
||||
|
||||
password_description: 'Contraseña',
|
||||
password_placeholder: 'Ingresa tu contraseña',
|
||||
password_placeholder2: 'Ingresa tu contraseña para confirmar',
|
||||
password_error: 'Las contraseñas deben contener no menos de 6 símbolos.',
|
||||
password_error1: 'La confirmación de la contraseña no coincide con la contraseña.',
|
||||
password_validation_title: 'Contraseña'
|
||||
|
||||
},
|
||||
sw: {
|
||||
phone_title: 'Tuma Namba ya Simu',
|
||||
phone_description: 'Pata marafiki kwa kutumia namba yako',
|
||||
phone_placeholder: 'Namba ya simu',
|
||||
|
||||
confirm_description: 'Kificho cha uthibitisho',
|
||||
confirm_validation_title: 'Kificho cha uthibitisho',
|
||||
confirm_validation_description: 'Muundo hafifu',
|
||||
|
||||
password_description: 'Nenosiri',
|
||||
password_placeholder: 'Andika nenosiri lako',
|
||||
password_placeholder2: 'Tafadhali ingiza tena nenosiri kuthibitisha',
|
||||
password_error: 'Nenosiri lisiwe chini ya alama 6.',
|
||||
password_error1: 'Uthibitisho wa nenosiri haulingani na nenosiri.',
|
||||
password_validation_title: 'Nenosiri'
|
||||
|
||||
},
|
||||
sv: {
|
||||
phone_title: 'Skicka telefonnummer',
|
||||
phone_description: 'Hitta vänner som använder ditt nummer',
|
||||
phone_placeholder: 'Telefonnummer',
|
||||
|
||||
confirm_description: 'Bekräftelsekod',
|
||||
confirm_validation_title: 'Bekräftelsekod',
|
||||
confirm_validation_description: 'Fel format',
|
||||
|
||||
password_description: 'Lösenord',
|
||||
password_placeholder: 'Skriv ditt lösenord',
|
||||
password_placeholder2: 'Var god ange ditt lösenord igen för att bekräfta',
|
||||
password_error: 'Lösenordet bör inte vara mindre än 6 symboler.',
|
||||
password_error1: 'Lösenordsbekräftelsen matcharinte lösenordet.',
|
||||
password_validation_title: 'Lösenord'
|
||||
|
||||
},
|
||||
'fr-ch': {
|
||||
phone_title: 'Envoyer numéro de téléphone',
|
||||
phone_description: 'Trouvez des amis en utilisant votre numéro',
|
||||
phone_placeholder: 'Numéro de téléphone',
|
||||
|
||||
confirm_description: 'Code de confirmation',
|
||||
confirm_validation_title: 'Code de confirmation',
|
||||
confirm_validation_description: 'Mauvais format',
|
||||
|
||||
password_description: 'Mot de passe',
|
||||
password_placeholder: 'Tapez votre mot de passe',
|
||||
password_placeholder2: 'Veuillez saisir à nouveau le mot de passe pour confirmer',
|
||||
password_error: 'Le mot de passe doit avoir au moins 6 caractères.',
|
||||
password_error1: 'La confirmation du mot de passe ne correspond pas au premier mot de passe.',
|
||||
password_validation_title: 'Mot de passe'
|
||||
|
||||
},
|
||||
'de-ch': {
|
||||
phone_title: 'Sende Telefonnummer',
|
||||
phone_description: 'Finde Freunde mittels deiner Telefonnummer',
|
||||
phone_placeholder: 'Telefonnummer',
|
||||
|
||||
confirm_description: 'Konfirmationscode',
|
||||
confirm_validation_title: 'Konfirmationscode',
|
||||
confirm_validation_description: 'Falsches Format',
|
||||
|
||||
password_description: 'Passwort',
|
||||
password_placeholder: 'Gib dein Passwort ein',
|
||||
password_placeholder2: 'Bitte gib das Passwort zur Bestätigung erneut ein',
|
||||
password_error: 'Passwort sollte nicht kleiner als 6 Symbole sein.',
|
||||
password_error1: 'Passwort Bestätigung stimmt mit Passwort nicht überein.',
|
||||
password_validation_title: 'Passwort'
|
||||
|
||||
},
|
||||
'it-ch': {
|
||||
phone_title: 'Invia numero di telefono',
|
||||
phone_description: 'Trova amici che utilizzano il tuo numero',
|
||||
phone_placeholder: 'Numero di telefono',
|
||||
|
||||
confirm_description: 'Codice di conferma',
|
||||
confirm_validation_title: 'Codice di conferma',
|
||||
confirm_validation_description: 'Formato errato',
|
||||
|
||||
password_description: 'Password',
|
||||
password_placeholder: 'Digita la tua password',
|
||||
password_placeholder2: 'Inserisci nuovamente la password per confermare',
|
||||
password_error: 'La password non può contenere meno di 6 caratteri.',
|
||||
password_error1: 'La password di conferma non corrisponde alla password.',
|
||||
password_validation_title: 'Password'
|
||||
|
||||
},
|
||||
th: {
|
||||
phone_title: 'ส่งหมายเลขโทรศัพท์',
|
||||
phone_description: 'ค้นหาเพื่อนโดยใช้หมายเลขของคุณ ',
|
||||
phone_placeholder: 'หมายเลขโทรศัพท์',
|
||||
|
||||
confirm_description: 'รหัสยืนยัน',
|
||||
confirm_validation_title: 'รหัสยืนยัน',
|
||||
confirm_validation_description: 'รูปแบบผิด',
|
||||
|
||||
password_description: 'รหัสผ่าน',
|
||||
password_placeholder: 'พิมพ์รหัสผ่านของคุณ',
|
||||
password_placeholder2: 'โปรดกรอกรหัสผ่านอีกครั้งเพื่อยืนยัน',
|
||||
password_error: 'รหัสผ่านควรมีสัญลักษณ์ไม่น้อยกว่า 6 ตัว',
|
||||
password_error1: 'การยืนยันรหัสผ่านไม่ตรงกับรหัสผ่าน',
|
||||
password_validation_title: 'รหัสผ่าน'
|
||||
|
||||
},
|
||||
tr: {
|
||||
phone_title: 'Telefon Numarasını Gönder',
|
||||
phone_description: 'Telefon numaranı kullanarak arkadaşlarınızı bulun',
|
||||
phone_placeholder: 'Telefon numarası',
|
||||
|
||||
confirm_description: 'Onay kodu',
|
||||
confirm_validation_title: 'Onay kodu',
|
||||
confirm_validation_description: 'Hatalı format',
|
||||
|
||||
password_description: 'Şifre',
|
||||
password_placeholder: 'Şifrenizi girin',
|
||||
password_placeholder2: 'Onaylamak için lütfen parolanızı yeniden girin',
|
||||
password_error: 'Şifre 6 simgeden daha kısa olmamalıdır.',
|
||||
password_error1: 'Şifre onayı, şifre ile eşleşmiyor.',
|
||||
password_validation_title: 'Şifre'
|
||||
|
||||
},
|
||||
uk: {
|
||||
phone_title: 'Надіслати номер телефону',
|
||||
phone_description: 'Знайдіть друзів, використовуючи свій номер',
|
||||
phone_placeholder: 'Номер телефону',
|
||||
|
||||
confirm_description: 'Код підтвердження',
|
||||
confirm_validation_title: 'Код підтвердження',
|
||||
confirm_validation_description: 'Неправильний формат',
|
||||
|
||||
password_description: 'Пароль',
|
||||
password_placeholder: 'Введіть свій пароль',
|
||||
password_placeholder2: 'Будь ласка, введіть пароль ще раз для підтвердження',
|
||||
password_error: 'Пароль повинен бути не менше 6 символів.',
|
||||
password_error1: 'Підтвердження паролю не співпадає з паролем.',
|
||||
password_validation_title: 'Пароль'
|
||||
|
||||
},
|
||||
ur: {
|
||||
phone_title: 'فون نمبر بھیجیں',
|
||||
phone_description: 'فون نمبر استعمال کرتے ہوئے دوستوں کو تلاش کریں',
|
||||
phone_placeholder: 'فون نمبر',
|
||||
|
||||
confirm_description: 'تصدیقی کوڈ',
|
||||
confirm_validation_title: 'تصدیقی کوڈ',
|
||||
confirm_validation_description: 'غلط فارمیٹ',
|
||||
|
||||
password_description: 'پاسورڈ',
|
||||
password_placeholder: 'اپنا پاسورڈ لکھیں',
|
||||
password_placeholder2: 'برائے مہربانی تصدیق کے لیے اپنا پاسورڈ دوبارہ لکھیں',
|
||||
password_error: 'پاسورڈ 6 اعداد سے چھوٹا نہیں ہونا چاہیے۔',
|
||||
password_error1: 'تصدیقی پاسورڈ پاسورڈ سے مماثل نہیں',
|
||||
password_validation_title: 'پاسورڈ'
|
||||
|
||||
},
|
||||
vi: {
|
||||
phone_title: 'Gửi số điện thoại',
|
||||
phone_description: 'Tìm bạn bè bằng các sử dụng số điện thoại của bạn',
|
||||
phone_placeholder: 'Số điện thoại',
|
||||
|
||||
confirm_description: 'Mã xác nhận',
|
||||
confirm_validation_title: 'Mã xác nhận',
|
||||
confirm_validation_description: 'Sai định dạng',
|
||||
|
||||
password_description: 'Mật khẩu',
|
||||
password_placeholder: 'Gõ mật khẩu của bạn',
|
||||
password_placeholder2: 'Vui lòng nhập lại mật khẩu để xác nhận',
|
||||
password_error: 'Mật khẩu không được ít hơn 6 ký tự.',
|
||||
password_error1: 'Xác nhận mật khẩu không khớp với mật khẩu.',
|
||||
password_validation_title: 'Mật khẩu'
|
||||
|
||||
}
|
||||
};
|
|
@ -0,0 +1,587 @@
|
|||
var WEB3_UNIT = [
|
||||
'kwei/ada',
|
||||
'mwei/babbage',
|
||||
'gwei/shannon',
|
||||
'szabo',
|
||||
'finney',
|
||||
'ether',
|
||||
'kether/grand/einstein',
|
||||
'mether',
|
||||
'gether',
|
||||
'tether'
|
||||
];
|
||||
|
||||
// because web3 doesn't provide params or docs
|
||||
var DOC_MAP = {
|
||||
console: {
|
||||
log : {
|
||||
desc: 'Outputs a message to chat context.',
|
||||
args: [{
|
||||
name: 'text',
|
||||
type: 'String',
|
||||
desc: 'message to output to chat context'
|
||||
}]
|
||||
}
|
||||
},
|
||||
web3: {
|
||||
// setProvider : ['provider'], // TODO
|
||||
version: {
|
||||
api: {
|
||||
desc: 'The ethereum js api version.'
|
||||
},
|
||||
node: {
|
||||
desc: 'The client/node version.'
|
||||
},
|
||||
network: {
|
||||
desc: 'The network protocol version.'
|
||||
},
|
||||
ethereum: {
|
||||
desc: 'The ethereum protocol version.'
|
||||
},
|
||||
whisper: {
|
||||
desc: 'The whisper protocol version.'
|
||||
},
|
||||
},
|
||||
isConnected: {
|
||||
desc: 'Check if a connection to a node exists.',
|
||||
args: []
|
||||
},
|
||||
currentProvider: {
|
||||
desc: 'Will contain the current provider, if one is set. This can be used to check if mist etc. set already a provider.'
|
||||
},
|
||||
reset: {
|
||||
desc: 'Should be called to reset state of web3. Resets everything except manager. Uninstalls all filters. Stops polling.',
|
||||
args: [{
|
||||
name: 'keepIsSyncing',
|
||||
type: 'Boolean',
|
||||
desc: 'If true it will uninstall all filters, but will keep the web3.eth.isSyncing() polls'
|
||||
}]
|
||||
},
|
||||
sha3: {
|
||||
desc: 'Returns the Keccak-256 SHA3 of the given data.',
|
||||
args: [{
|
||||
name: 'string',
|
||||
type: 'String',
|
||||
desc: 'The string to hash using the Keccak-256 SHA3 algorithm'
|
||||
}, {
|
||||
name: 'options',
|
||||
type: 'Object',
|
||||
optional: true,
|
||||
desc: 'Set encoding to hex if the string to hash is encoded in hex. A leading 0x will be automatically ignored.'
|
||||
}]
|
||||
},
|
||||
toHex: {
|
||||
desc: 'Converts any value into HEX',
|
||||
args: [{
|
||||
name: 'mixed',
|
||||
type: 'String|Number|Object|Array|BigNumber',
|
||||
desc: 'The value to parse to HEX. If its an object or array it will be JSON.stringify first. If its a BigNumber it will make it the HEX value of a number.'
|
||||
}]
|
||||
},
|
||||
toAscii: {
|
||||
desc: 'Converts a HEX string into a ASCII string.',
|
||||
args: [{
|
||||
name: 'hexString',
|
||||
type: 'String',
|
||||
desc: 'A HEX string to be converted to ascii.'
|
||||
}]
|
||||
},
|
||||
fromAscii: {
|
||||
desc: 'Converts any ASCII string to a HEX string.',
|
||||
args: [{
|
||||
name: 'string',
|
||||
type: 'String',
|
||||
desc: 'An ASCII string to be converted to HEX.'
|
||||
}, {
|
||||
name: 'padding',
|
||||
type: 'Number',
|
||||
desc: 'The number of bytes the returned HEX string should have. '
|
||||
}]
|
||||
},
|
||||
toDecimal: {
|
||||
desc: 'Converts a HEX string to its number representation.',
|
||||
args: [{
|
||||
name: 'hexString',
|
||||
type: 'String',
|
||||
desc: 'An HEX string to be converted to a number.'
|
||||
}]
|
||||
},
|
||||
fromDecimal: {
|
||||
desc: 'Converts a number or number string to its HEX representation.',
|
||||
args: [{
|
||||
name: 'number',
|
||||
type: 'Number',
|
||||
desc: 'A number to be converted to a HEX string.'
|
||||
}]
|
||||
},
|
||||
fromWei: {
|
||||
desc: 'Converts a number of wei into an ethereum unit',
|
||||
args: [{
|
||||
name: 'number',
|
||||
type: 'Number|String|BigNumber',
|
||||
desc: 'A number or BigNumber instance.'
|
||||
}, {
|
||||
name: 'unit',
|
||||
type: 'string',
|
||||
desc: 'One of the ether units'
|
||||
}]
|
||||
},
|
||||
toWei: {
|
||||
desc: 'Converts an ethereum unit into wei',
|
||||
args: [{
|
||||
name: 'number',
|
||||
type: 'Number|String|BigNumber',
|
||||
desc: 'A number or BigNumber instance.'
|
||||
}, {
|
||||
name: 'unit',
|
||||
type: 'string',
|
||||
desc: 'One of the ether units'
|
||||
}]
|
||||
},
|
||||
toBigNumber: {
|
||||
desc: 'Converts a given number into a BigNumber instance',
|
||||
args: [{
|
||||
name: 'numberOrHexString',
|
||||
type: 'Number|String',
|
||||
desc: 'A number, number string or HEX string of a number.'
|
||||
}]
|
||||
},
|
||||
net: {
|
||||
listening: {
|
||||
desc: 'Is node actively listening for network connections?'
|
||||
},
|
||||
peerCount: {
|
||||
desc: 'Returns the number of connected peers'
|
||||
}
|
||||
},
|
||||
isAddress: {
|
||||
desc: '',
|
||||
args: [{
|
||||
name: '',
|
||||
type: 'string',
|
||||
desc: 'hex string'
|
||||
}], // TODO not in docs
|
||||
},
|
||||
eth: {
|
||||
defaultAccount: {
|
||||
desc: 'The currently set default address'
|
||||
},
|
||||
defaultBlock: {
|
||||
desc: 'The default block number to use when querying a state.'
|
||||
},
|
||||
syncing: {
|
||||
desc: 'Returns the either a sync object, when the node is syncing or false.'
|
||||
},
|
||||
isSyncing: {
|
||||
desc: 'This convenience function calls the callback everytime a sync starts, updates and stops.',
|
||||
args: [{
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
desc: 'The callback will be fired with true when the syncing starts and with false when it stopped. While syncing it will return the syncing object: {startingBlock, currentBlock, highestBlock}'
|
||||
}]
|
||||
},
|
||||
coinbase: {
|
||||
desc: 'Returns the coinbase address were the mining rewards go to.'
|
||||
},
|
||||
mining: {
|
||||
desc: 'Says whether the node is mining or not.'
|
||||
},
|
||||
hashrate: {
|
||||
desc: 'Returns the number of hashes per second that the node is mining with.'
|
||||
},
|
||||
gasPrice: {
|
||||
desc: 'Returns the current gas price. The gas price is determined by the x latest blocks median gas price'
|
||||
},
|
||||
accounts: {
|
||||
desc: 'Returns a list of accounts the node controls'
|
||||
},
|
||||
blockNumber: {
|
||||
desc: 'Returns the current block number'
|
||||
},
|
||||
getBalance: {
|
||||
desc: 'Get the balance of an address at a given block.',
|
||||
args: [{
|
||||
name: 'addressHexString',
|
||||
type: 'String',
|
||||
desc: 'The address to get the balance of'
|
||||
}, {
|
||||
name: 'defaultBlock',
|
||||
type: 'Number|String',
|
||||
optional: true,
|
||||
desc: 'If you pass this parameter it will not use the default block set with web3.eth.defaultBlock.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getStorageAt: {
|
||||
desc: 'Get the storage at a specific position of an address.',
|
||||
args: [{
|
||||
name: 'addressHexString',
|
||||
type: 'String',
|
||||
desc: 'The address to get the storage from.'
|
||||
}, {
|
||||
name: 'position',
|
||||
type: 'Number',
|
||||
desc: 'The index position of the storage.'
|
||||
}, {
|
||||
name: 'defaultBlock',
|
||||
type: 'Number|String',
|
||||
optional: true,
|
||||
desc: 'If you pass this parameter it will not use the default block set with web3.eth.defaultBlock.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getCode: {
|
||||
desc: 'Get the code at a specific address.',
|
||||
args: [{
|
||||
name: 'addressHexString',
|
||||
type: 'String',
|
||||
desc: 'The address to get the code from.'
|
||||
}, {
|
||||
name: 'defaultBlock',
|
||||
type: 'Number|String',
|
||||
optional: true,
|
||||
desc: 'If you pass this parameter it will not use the default block set with web3.eth.defaultBlock.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getBlock: {
|
||||
desc: 'Returns a block matching the block number or block hash.',
|
||||
args: [{
|
||||
name: 'blockHashOrBlockNumber',
|
||||
type: 'String|Number',
|
||||
desc: 'The block number or hash. Or the string "earliest", "latest" or "pending"'
|
||||
}, {
|
||||
name: 'returnTransactionObjects',
|
||||
type: 'Boolean',
|
||||
optional: true,
|
||||
desc: '(default false) If true, the returned block will contain all transactions as objects, if false it will only contains the transaction hashes.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getBlockTransactionCount: {
|
||||
desc: 'Returns the number of transaction in a given block.',
|
||||
args: [{
|
||||
name: 'hashStringOrBlockNumber',
|
||||
type: 'String|Number',
|
||||
desc: 'The block number or hash. Or the string "earliest", "latest" or "pending"'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getUncle: {
|
||||
desc: 'Returns a blocks uncle by a given uncle index position',
|
||||
args: [{
|
||||
name: 'blockHashStringOrNumber',
|
||||
type: 'String|Number',
|
||||
desc: 'The block number or hash. Or the string "earliest", "latest" or "pending"'
|
||||
}, {
|
||||
name: 'uncleNumber',
|
||||
type: 'Number',
|
||||
desc: 'The index position of the uncle.'
|
||||
}, {
|
||||
name: 'returnTransactionObjects',
|
||||
type: 'Boolean',
|
||||
desc: '(default false) If true, the returned block will contain all transactions as objects, if false it will only contains the transaction hashes.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getBlockUncleCount: {
|
||||
desc: '', // TODO missing from docs
|
||||
},
|
||||
getTransaction: {
|
||||
desc: 'Returns a transaction matching the given transaction hash.',
|
||||
args: [{
|
||||
name: 'transactionHash',
|
||||
type: 'String',
|
||||
desc: 'The transaction hash.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getTransactionFromBlock: {
|
||||
desc: 'Returns a transaction based on a block hash or number and the transactions index position.',
|
||||
args: [{
|
||||
name: 'hashStringOrBlockNumber',
|
||||
type: 'String|Number',
|
||||
desc: 'The block number or hash. Or the string "earliest", "latest" or "pending"'
|
||||
}, {
|
||||
name: 'indexNumber',
|
||||
type: 'Number',
|
||||
desc: 'The transactions index position.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getTransactionReceipt: {
|
||||
desc: 'Returns the receipt of a transaction by transaction hash.',
|
||||
args: [{
|
||||
name: 'hashString',
|
||||
type: 'String',
|
||||
desc: 'The transaction hash.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
getTransactionCount: {
|
||||
desc: 'Get the numbers of transactions sent from this address.',
|
||||
args: [{
|
||||
name: 'addressHexString',
|
||||
type: 'String',
|
||||
desc: 'The address to get the numbers of transactions from.'
|
||||
}, {
|
||||
name: 'defaultBlock',
|
||||
type: 'String|Number',
|
||||
desc: 'If you pass this parameter it will not use the default block set with web3.eth.defaultBlock.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
sendTransaction: {
|
||||
desc: 'Sends a transaction to the network.',
|
||||
args: [{
|
||||
name: 'transactionObject',
|
||||
type: 'Object',
|
||||
desc: 'The transaction object to send: {from[, to][, value][, gas][, gasPrice][, data][, nonce]}'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
sendRawTransaction: {
|
||||
desc: 'Sends an already signed transaction.',
|
||||
args: [{
|
||||
name: 'signedTransactionData',
|
||||
type: 'String',
|
||||
desc: 'Signed transaction data in HEX format'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
sign: {
|
||||
desc: 'Signs data from a specific account. This account needs to be unlocked.',
|
||||
args: [{
|
||||
name: 'address',
|
||||
type: 'String',
|
||||
desc: 'Address to sign with.'
|
||||
}, {
|
||||
name: 'dataToSign',
|
||||
type: 'String',
|
||||
desc: 'Data to sign.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
call: {
|
||||
desc: 'Executes a message call transaction, which is directly executed in the VM of the node, but never mined into the blockchain.',
|
||||
args: [{
|
||||
name: 'callObject',
|
||||
type: 'String',
|
||||
desc: 'Address to sign with.'
|
||||
}, {
|
||||
name: 'defaultBlock',
|
||||
type: 'String',
|
||||
optional: true,
|
||||
desc: 'Data to sign.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
estimateGas: {
|
||||
desc: 'Executes a message call or transaction, which is directly executed in the VM of the node, but never mined into the blockchain and returns the amount of the gas used.',
|
||||
args: [{
|
||||
name: 'callObject',
|
||||
type: 'Object',
|
||||
desc: 'The transaction object to send: {[from][, to][, value][, gas][, gasPrice][, data][, nonce]}'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
filter: {
|
||||
// TODO: add description
|
||||
desc: '',
|
||||
args: [{
|
||||
name: 'options',
|
||||
type: 'String|Object',
|
||||
desc: 'The string "latest" or "pending" to watch for changes in the latest block or pending transactions respectively. Or a filter options object as follows: {fromBlock: Number|String, toBlock: Number|String, address: String, topics: StringArray}'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'Watch callback'
|
||||
}]
|
||||
},
|
||||
// TODO filters
|
||||
// watch : ['callback'],
|
||||
// stopWatching : ['callback'],
|
||||
contract: {
|
||||
desc: 'Creates a contract object for a solidity contract, which can be used to initiate contracts on an address.',
|
||||
args: [{
|
||||
name: 'abiArray',
|
||||
type: 'Array',
|
||||
desc: 'ABI array with descriptions of functions and events of the contract.'
|
||||
}]
|
||||
},
|
||||
getCompilers: {
|
||||
desc: 'Gets a list of available compilers.',
|
||||
args: [{
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'If you pass a callback the HTTP request is made asynchronous.'
|
||||
}]
|
||||
},
|
||||
compile: { // TODO we should auto hide these depending on output from getCompilers
|
||||
lll: {
|
||||
desc: 'Compiles LLL source code.',
|
||||
args: [{
|
||||
name: 'sourceString',
|
||||
type: 'String',
|
||||
desc: 'The LLL source code.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'Watch callback'
|
||||
}]
|
||||
},
|
||||
solidity: {
|
||||
desc: 'Compiles solidity source code',
|
||||
args: [{
|
||||
name: 'sourceString',
|
||||
type: 'String',
|
||||
desc: 'The solidity source code.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'Watch callback'
|
||||
}],
|
||||
},
|
||||
serpent: {
|
||||
desc: 'Compiles serpent source code',
|
||||
args: [{
|
||||
name: 'sourceString',
|
||||
type: 'String',
|
||||
desc: 'The serpent source code.'
|
||||
}, {
|
||||
name: 'callback',
|
||||
type: 'Function',
|
||||
optional: true,
|
||||
desc: 'Watch callback'
|
||||
}]
|
||||
}
|
||||
},
|
||||
namereg: {
|
||||
desc: 'Returns GlobalRegistrar object.'
|
||||
}
|
||||
},
|
||||
|
||||
db: {
|
||||
putString: {
|
||||
desc: 'Store a string in the local leveldb database.',
|
||||
args: [{
|
||||
name: 'db',
|
||||
type: 'String',
|
||||
desc: 'The database to store to.'
|
||||
}, {
|
||||
name: 'key',
|
||||
type: 'String',
|
||||
desc: 'The name of the store.'
|
||||
}, {
|
||||
name: 'value',
|
||||
type: 'String',
|
||||
desc: 'The string value to store.'
|
||||
}]
|
||||
},
|
||||
getString: {
|
||||
desc: 'Retrieve a string from the local leveldb database. (db, key)',
|
||||
args: [{
|
||||
name: 'db',
|
||||
type: 'String',
|
||||
desc: 'The database string name to retrieve from.'
|
||||
}, {
|
||||
name: 'key',
|
||||
type: 'String',
|
||||
desc: 'The name of the store.'
|
||||
}]
|
||||
},
|
||||
putHex: {
|
||||
desc: 'Store binary data in the local leveldb database. (db, key, value)',
|
||||
args: [{
|
||||
name: 'db',
|
||||
type: 'String',
|
||||
desc: 'The database to store to.'
|
||||
}, {
|
||||
name: 'key',
|
||||
type: 'String',
|
||||
desc: 'The name of the store.'
|
||||
}, {
|
||||
name: 'value',
|
||||
type: 'String',
|
||||
desc: 'The HEX string to store.'
|
||||
}]
|
||||
},
|
||||
getHex: {
|
||||
desc: 'Retrieve binary data from the local leveldb database. (db, key)',
|
||||
args: [{
|
||||
name: 'db',
|
||||
type: 'String',
|
||||
desc: 'The database string name to retrieve from.'
|
||||
}, {
|
||||
name: 'key',
|
||||
type: 'String',
|
||||
desc: 'The name of the store.'
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,99 @@
|
|||
function round(n) {
|
||||
return Math.round(n * 100) / 100;
|
||||
}
|
||||
|
||||
function doubledValueLabel(params) {
|
||||
var value = round(params.value);
|
||||
return "sliderValue = " + value +
|
||||
"; (2 * sliderValue) = " + (2 * value);
|
||||
}
|
||||
|
||||
status.defineSubscription(
|
||||
// the name of subscription and the name of the value in bot-db
|
||||
// associated with this subscription
|
||||
"doubledValue",
|
||||
// the map of values on which subscription depends: keys are arbitrary names
|
||||
// and values are db paths to another value
|
||||
{value: ["sliderValue"]},
|
||||
// the function which will be called as reaction on changes of values above,
|
||||
// should be pure. Returned result will be associated with subscription in bot-db
|
||||
doubledValueLabel
|
||||
);
|
||||
|
||||
status.defineSubscription(
|
||||
"roundedValue",
|
||||
{value: ["sliderValue"]},
|
||||
function (params) {
|
||||
return round(params.value);
|
||||
}
|
||||
)
|
||||
|
||||
function superSuggestion(params, context) {
|
||||
var balance = parseFloat(web3.fromWei(web3.eth.getBalance(context.from), "ether"));
|
||||
var defaultSliderValue = balance / 2;
|
||||
|
||||
var view = ["view", {},
|
||||
["text", {}, "Balance " + balance + " ETH"],
|
||||
["text", {}, ["subscribe", ["doubledValue"]]],
|
||||
["slider", {
|
||||
maximumValue: ["subscribe", ["balance"]],
|
||||
value: defaultSliderValue,
|
||||
minimumValue: 0,
|
||||
onSlidingComplete: ["dispatch", ["set", "sliderValue"]],
|
||||
step: 0.05
|
||||
}],
|
||||
['touchable',
|
||||
{onPress: ['dispatch', ["set-value-from-db", "roundedValue"]]},
|
||||
["view", {}, ["text", {}, "Set value"]]
|
||||
],
|
||||
["text", {style: {color: "red"}}, ["subscribe", ["validationText"]]]
|
||||
];
|
||||
|
||||
status.setDefaultDb({
|
||||
sliderValue: defaultSliderValue,
|
||||
doubledValue: doubledValueLabel({value: defaultSliderValue})
|
||||
});
|
||||
|
||||
var validationText = "";
|
||||
|
||||
if (isNaN(params.message)) {
|
||||
validationText = "That's not a float number!";
|
||||
} else if (parseFloat(params.message) > balance) {
|
||||
validationText =
|
||||
"Input value is too big!" +
|
||||
" You have only " + balance + " ETH on your balance!";
|
||||
}
|
||||
|
||||
status.updateDb({
|
||||
balance: balance,
|
||||
validationText: validationText
|
||||
});
|
||||
|
||||
status.setSuggestions(view);
|
||||
};
|
||||
|
||||
status.on("text-change", superSuggestion);
|
||||
status.on("message", function (params, context) {
|
||||
if (isNaN(params.message)) {
|
||||
status.sendMessage("Seems that you don't want to send money :(");
|
||||
return;
|
||||
}
|
||||
|
||||
var balance = web3.eth.getBalance(context.from);
|
||||
var value = parseFloat(params.message);
|
||||
var weiValue = web3.toWei(value, "ether");
|
||||
if (bn(weiValue).greaterThan(bn(balance))) {
|
||||
status.sendMessage("No way man, you don't have enough money! :)");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
web3.eth.sendTransaction({
|
||||
from: context.from,
|
||||
to: context.from,
|
||||
value: weiValue
|
||||
});
|
||||
status.sendMessage("You are the hero, you sent " + value + " ETH to yourself!");
|
||||
} catch (err) {
|
||||
status.sendMessage("Something went wrong :(")
|
||||
}
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
status.command({
|
||||
name: "location",
|
||||
icon: "location",
|
||||
title: I18n.t('location_title'),
|
||||
description: I18n.t('location_description'),
|
||||
color: "#a187d5",
|
||||
sequentialParams: true,
|
||||
preview: function (params) {
|
||||
var text = status.components.text(
|
||||
{
|
||||
style: {
|
||||
marginTop: 5,
|
||||
marginHorizontal: 0,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "black"
|
||||
}
|
||||
}, params.address);
|
||||
var uri = "https://maps.googleapis.com/maps/api/staticmap?center="
|
||||
+ params.address
|
||||
+ "&size=100x100&maptype=roadmap&key=AIzaSyBNsj1qoQEYPb3IllmWMAscuXW0eeuYqAA&language=en"
|
||||
+ "&markers=size:mid%7Ccolor:0xff0000%7Clabel:%7C"
|
||||
+ params.address;
|
||||
|
||||
var image = status.components.image(
|
||||
{
|
||||
source: {uri: uri},
|
||||
style: {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return {markup: status.components.view({}, [text, image])};
|
||||
},
|
||||
shortPreview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('location_title') + ": " + params.address
|
||||
)
|
||||
};
|
||||
}
|
||||
}).param({
|
||||
name: "address",
|
||||
type: status.types.TEXT,
|
||||
placeholder: I18n.t('location_address')
|
||||
});
|
|
@ -0,0 +1,167 @@
|
|||
I18n.translations = {
|
||||
en: {
|
||||
location_title: 'Location',
|
||||
location_description: 'Share your location',
|
||||
location_address: 'Address'
|
||||
},
|
||||
ru: {
|
||||
location_title: 'Местоположение',
|
||||
location_description: 'Поделитесь своим местоположением',
|
||||
location_address: 'Адрес'
|
||||
},
|
||||
af: {
|
||||
location_title: 'Ligging',
|
||||
location_description: 'Deel jou ligging',
|
||||
location_address: 'Addres'
|
||||
},
|
||||
ar: {
|
||||
location_title: 'الموقع',
|
||||
location_description: 'شارك موقعك',
|
||||
location_address: 'العنوان'
|
||||
},
|
||||
'zh-hant': {
|
||||
location_title: '位置',
|
||||
location_description: '分享您的位置',
|
||||
location_address: '地址'
|
||||
},
|
||||
'zh-hans': {
|
||||
location_title: '位置',
|
||||
location_description: '分享你的位置',
|
||||
location_address: '地址'
|
||||
},
|
||||
'zh-yue': {
|
||||
location_title: '所在位置',
|
||||
location_description: '分享所在位置',
|
||||
location_address: '地址'
|
||||
},
|
||||
'zh-wuu': {
|
||||
location_title: '位置',
|
||||
location_description: '分享您的位置',
|
||||
location_address: '地址'
|
||||
},
|
||||
nl: {
|
||||
location_title: 'Locatie',
|
||||
location_description: 'Deel je locatie',
|
||||
location_address: 'Adres'
|
||||
},
|
||||
fr: {
|
||||
location_title: 'Emplacement',
|
||||
location_description: 'Partager votre emplacement',
|
||||
location_address: 'Adresse'
|
||||
},
|
||||
de: {
|
||||
location_title: 'Ort',
|
||||
location_description: 'Teilen Sie Ihren Ort',
|
||||
location_address: 'Adresse'
|
||||
},
|
||||
hi: {
|
||||
location_title: 'स्थान',
|
||||
location_description: 'अपना स्थान साझा करें',
|
||||
location_address: 'पता'
|
||||
},
|
||||
hu: {
|
||||
location_title: 'Helyszín',
|
||||
location_description: 'Helyszín megosztása',
|
||||
location_address: 'Cím'
|
||||
},
|
||||
it: {
|
||||
location_title: 'Posizione',
|
||||
location_description: 'Condividi la tua posizione',
|
||||
location_address: 'Indirizzo'
|
||||
},
|
||||
ja: {
|
||||
location_title: '位置',
|
||||
location_description: '位置情報を共有',
|
||||
location_address: 'アドレス'
|
||||
},
|
||||
ko: {
|
||||
location_title: '위치',
|
||||
location_description: '내 위치 공유하기',
|
||||
location_address: '주소'
|
||||
},
|
||||
pl: {
|
||||
location_title: 'Lokalizacja',
|
||||
location_description: 'Udostępnij swoją lokalizację',
|
||||
location_address: 'Adres'
|
||||
},
|
||||
'pt-br': {
|
||||
location_title: 'Localização',
|
||||
location_description: 'Compartilhar sua localização',
|
||||
location_address: 'Endereço'
|
||||
},
|
||||
'pt-pt': {
|
||||
location_title: 'Location',
|
||||
location_description: 'Partilhar a sua localização',
|
||||
location_address: 'Endereço'
|
||||
},
|
||||
ro: {
|
||||
location_title: 'Locație',
|
||||
location_description: "Partajează locația",
|
||||
location_address: 'Adresă'
|
||||
},
|
||||
sl: {
|
||||
location_title: 'Lokacija',
|
||||
location_description: 'Deli svojo lokacijo',
|
||||
location_address: 'Naslov'
|
||||
},
|
||||
es: {
|
||||
location_title: 'Ubicación',
|
||||
location_description: 'Comparte tu ubicación',
|
||||
location_address: 'Dirección'
|
||||
},
|
||||
'es-ar': {
|
||||
location_title: 'Ubicación',
|
||||
location_description: 'Comparte tu ubicación',
|
||||
location_address: 'Dirección'
|
||||
},
|
||||
sw: {
|
||||
location_title: 'Eneo',
|
||||
location_description: 'Shiriki eneo lako',
|
||||
location_address: 'Anwani'
|
||||
},
|
||||
sv: {
|
||||
location_title: 'Plats',
|
||||
location_description: 'Dela din plats',
|
||||
location_address: 'Adress'
|
||||
},
|
||||
'fr-ch': {
|
||||
location_title: 'Emplacement',
|
||||
location_description: 'Partagez votre emplacement',
|
||||
location_address: 'Adresse'
|
||||
},
|
||||
'de-ch': {
|
||||
location_title: 'Standort',
|
||||
location_description: 'Teile deinen Standort',
|
||||
location_address: 'Adresse'
|
||||
},
|
||||
'it-ch': {
|
||||
location_title: 'Posizione',
|
||||
location_description: 'Condividi la tua posizione',
|
||||
location_address: 'Indirizzo'
|
||||
},
|
||||
th: {
|
||||
location_title: 'ตำแหน่ง',
|
||||
location_description: 'แชร์ตำแหน่งของคุณ',
|
||||
location_address: 'ที่อยู่'
|
||||
},
|
||||
tr: {
|
||||
location_title: 'Konum',
|
||||
location_description: 'Konumunuzu paylaşın',
|
||||
location_address: 'Adres'
|
||||
},
|
||||
uk: {
|
||||
location_title: 'Місцезнаходження',
|
||||
location_description: 'Поділіться своїм місцезнаходженням',
|
||||
location_address: 'Адреса'
|
||||
},
|
||||
ur: {
|
||||
location_title: 'مقام',
|
||||
location_description: 'اپنا مقام بتائیں',
|
||||
location_address: 'پتہ'
|
||||
},
|
||||
vi: {
|
||||
location_title: 'Vị trí',
|
||||
location_description: 'Chia sẻ vị trí của bạn',
|
||||
location_address: 'Địa chỉ'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,217 @@
|
|||
function validateSend(params, context) {
|
||||
if (!context.to) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
"Wrong address",
|
||||
"Recipient address must be specified"
|
||||
)
|
||||
};
|
||||
}
|
||||
if (!params.amount) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_amount_specified')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
var amount = params.amount.replace(",", ".");
|
||||
var amountSplitted = amount.split(".");
|
||||
if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_amount_is_too_small')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
var val = web3.toWei(amount, "ether");
|
||||
if (val <= 0) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_invalid_number')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
var balance = web3.eth.getBalance(context.from);
|
||||
var estimatedGas = web3.eth.estimateGas({
|
||||
from: context.from,
|
||||
to: context.to,
|
||||
value: val
|
||||
});
|
||||
|
||||
if (bn(val).plus(bn(estimatedGas)).greaterThan(bn(balance))) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_insufficient_amount')
|
||||
+ web3.fromWei(balance, "ether")
|
||||
+ " ETH)"
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function sendTransaction(params, context) {
|
||||
var data = {
|
||||
from: context.from,
|
||||
to: context.to,
|
||||
value: web3.toWei(params.amount.replace(",", "."), "ether")
|
||||
};
|
||||
|
||||
try {
|
||||
return web3.eth.sendTransaction(data);
|
||||
} catch (err) {
|
||||
return {error: err.message};
|
||||
}
|
||||
}
|
||||
|
||||
var send = {
|
||||
name: "send",
|
||||
icon: "money_white",
|
||||
color: "#5fc48d",
|
||||
title: I18n.t('send_title'),
|
||||
description: I18n.t('send_description'),
|
||||
sequentialParams: true,
|
||||
params: [{
|
||||
name: "amount",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
preview: function (params, context) {
|
||||
var amountStyle = {
|
||||
fontSize: 36,
|
||||
color: "#000000",
|
||||
height: 40
|
||||
};
|
||||
|
||||
var amount = status.components.view(
|
||||
{
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
[status.components.text(
|
||||
{
|
||||
style: amountStyle,
|
||||
font: "light"
|
||||
},
|
||||
status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
)]);
|
||||
|
||||
var currency = status.components.view(
|
||||
{
|
||||
style: {
|
||||
flexDirection: "column",
|
||||
justifyContent: "flex-end",
|
||||
paddingBottom: 0
|
||||
}
|
||||
},
|
||||
[status.components.text(
|
||||
{
|
||||
style: {
|
||||
color: "#9199a0",
|
||||
fontSize: 16,
|
||||
lineHeight: 18,
|
||||
marginLeft: 7.5
|
||||
}
|
||||
},
|
||||
"ETH"
|
||||
)]
|
||||
);
|
||||
|
||||
return {
|
||||
markup: status.components.view(
|
||||
{
|
||||
style: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
marginTop: 8,
|
||||
marginBottom: 8
|
||||
}
|
||||
},
|
||||
[amount, currency]
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('send_title') + ": "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
handler: sendTransaction,
|
||||
validator: validateSend
|
||||
};
|
||||
|
||||
status.command(send);
|
||||
status.response(send);
|
||||
|
||||
status.command({
|
||||
name: "request",
|
||||
color: "#5fc48d",
|
||||
title: I18n.t('request_title'),
|
||||
description: I18n.t('request_description'),
|
||||
sequentialParams: true,
|
||||
params: [{
|
||||
name: "amount",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
handler: function (params) {
|
||||
return {
|
||||
event: "request",
|
||||
params: [params.amount],
|
||||
request: {
|
||||
command: "send",
|
||||
params: {
|
||||
amount: params.amount
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
preview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('request_requesting') + " "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('request_requesting') + " "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
validator: function (params) {
|
||||
try {
|
||||
var val = web3.toWei(params.amount.replace(",", "."), "ether");
|
||||
if (val <= 0) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_invalid_number')
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,12 +1,5 @@
|
|||
I18n.translations = {
|
||||
en: {
|
||||
location_title: 'Location',
|
||||
location_description: 'Send location',
|
||||
location_address: 'Address',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Open web browser',
|
||||
|
||||
send_title: 'Send ETH',
|
||||
send_description: 'Send a payment',
|
||||
|
||||
|
@ -21,13 +14,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Insufficient funds for gas * price + value (balance '
|
||||
},
|
||||
ru: {
|
||||
location_title: 'Местоположение',
|
||||
location_description: 'Поделитесь своим местоположением',
|
||||
location_address: 'Адрес',
|
||||
|
||||
browse_title: 'Браузер',
|
||||
browse_description: 'Запуск браузера',
|
||||
|
||||
send_title: 'Отправить ETH',
|
||||
send_description: 'Отправить платеж',
|
||||
|
||||
|
@ -42,13 +28,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Недостаточно ETH на балансе ('
|
||||
},
|
||||
af: {
|
||||
location_title: 'Ligging',
|
||||
location_description: 'Deel jou ligging',
|
||||
location_address: 'Addres',
|
||||
|
||||
browse_title: 'Webblaaier',
|
||||
browse_description: 'Begin die webblaaier',
|
||||
|
||||
send_title: 'Stuur ETH',
|
||||
send_description: 'Stuur \'n betaling',
|
||||
|
||||
|
@ -62,13 +41,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Nie genoeg ETH in rekening nie ('
|
||||
},
|
||||
ar: {
|
||||
location_title: 'الموقع',
|
||||
location_description: 'شارك موقعك',
|
||||
location_address: 'العنوان',
|
||||
|
||||
browse_title: 'المتصفح',
|
||||
browse_description: 'تشغيل المتصفح',
|
||||
|
||||
send_title: 'إرسال ETH',
|
||||
send_description: 'إرسال مدفوعات',
|
||||
|
||||
|
@ -82,13 +54,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'لا يوجد ETH كافي بالحساب ('
|
||||
},
|
||||
'zh-hant': {
|
||||
location_title: '位置',
|
||||
location_description: '分享您的位置',
|
||||
location_address: '地址',
|
||||
|
||||
browse_title: '流覽器',
|
||||
browse_description: '啟動流覽器',
|
||||
|
||||
send_title: '發送 ETH',
|
||||
send_description: '發送一筆付款',
|
||||
|
||||
|
@ -102,13 +67,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: '餘額中 ETH 不足 ('
|
||||
},
|
||||
'zh-hans': {
|
||||
location_title: '位置',
|
||||
location_description: '分享你的位置',
|
||||
location_address: '地址',
|
||||
|
||||
browse_title: '浏览器',
|
||||
browse_description: '启动浏览器',
|
||||
|
||||
send_title: '发送ETH',
|
||||
send_description: '付款',
|
||||
|
||||
|
@ -122,13 +80,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH余额不足 ('
|
||||
},
|
||||
'zh-yue': {
|
||||
location_title: '所在位置',
|
||||
location_description: '分享所在位置',
|
||||
location_address: '地址',
|
||||
|
||||
browse_title: '瀏覽器',
|
||||
browse_description: '啟動瀏覽器',
|
||||
|
||||
send_title: '發送ETH',
|
||||
send_description: '發送付款',
|
||||
|
||||
|
@ -142,13 +93,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: '沒有足夠ETH餘額 ('
|
||||
},
|
||||
'zh-wuu': {
|
||||
location_title: '位置',
|
||||
location_description: '分享您的位置',
|
||||
location_address: '地址',
|
||||
|
||||
browse_title: '浏览器',
|
||||
browse_description: '启动浏览器',
|
||||
|
||||
send_title: '发送ETH',
|
||||
send_description: '发送付款',
|
||||
|
||||
|
@ -162,13 +106,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH余额不足 ('
|
||||
},
|
||||
nl: {
|
||||
location_title: 'Locatie',
|
||||
location_description: 'Deel je locatie',
|
||||
location_address: 'Adres',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Start de browser',
|
||||
|
||||
send_title: 'Stuur ETH',
|
||||
send_description: 'Stuur een betaling',
|
||||
|
||||
|
@ -182,13 +119,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Niet genoeg ETH op saldo ('
|
||||
},
|
||||
fr: {
|
||||
location_title: 'Emplacement',
|
||||
location_description: 'Partager votre emplacement',
|
||||
location_address: 'Adresse',
|
||||
|
||||
browse_title: 'Navigateur',
|
||||
browse_description: 'Lancer le navigateur',
|
||||
|
||||
send_title: 'Envoyer l\'ETH',
|
||||
send_description: 'Envoyer un paiement',
|
||||
|
||||
|
@ -202,13 +132,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Pas assez d\'ETH sur le solde ('
|
||||
},
|
||||
de: {
|
||||
location_title: 'Ort',
|
||||
location_description: 'Teilen Sie Ihren Ort',
|
||||
location_address: 'Adresse',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Browser starten',
|
||||
|
||||
send_title: 'ETH abschicken',
|
||||
send_description: 'Zahlung senden',
|
||||
|
||||
|
@ -222,13 +145,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Nicht genügend ETH auf dem Konto ('
|
||||
},
|
||||
hi: {
|
||||
location_title: 'स्थान',
|
||||
location_description: 'अपना स्थान साझा करें',
|
||||
location_address: 'पता',
|
||||
|
||||
browse_title: 'ब्राउज़र',
|
||||
browse_description: 'ब्राउज़र लॉन्च करें',
|
||||
|
||||
send_title: 'ETH भेजें',
|
||||
send_description: 'भुगतान भेजें',
|
||||
|
||||
|
@ -242,13 +158,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'बैलेंस पर पर्याप्त ETH नहीं है ('
|
||||
},
|
||||
hu: {
|
||||
location_title: 'Helyszín',
|
||||
location_description: 'Helyszín megosztása',
|
||||
location_address: 'Cím',
|
||||
|
||||
browse_title: 'Böngésző',
|
||||
browse_description: 'Böngésző indítása',
|
||||
|
||||
send_title: 'ETH küldése',
|
||||
send_description: 'Kifizetés küldése',
|
||||
|
||||
|
@ -262,13 +171,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Nincs elég ETH a számlán ('
|
||||
},
|
||||
it: {
|
||||
location_title: 'Posizione',
|
||||
location_description: 'Condividi la tua posizione',
|
||||
location_address: 'Indirizzo',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Lancia il browser',
|
||||
|
||||
send_title: 'Invia ETH',
|
||||
send_description: 'Invia un pagamento',
|
||||
|
||||
|
@ -282,13 +184,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH insufficiente sul bilancio ('
|
||||
},
|
||||
ja: {
|
||||
location_title: '位置',
|
||||
location_description: '位置情報を共有',
|
||||
location_address: 'アドレス',
|
||||
|
||||
browse_title: 'ブラウザ',
|
||||
browse_description: 'ブラウザを起動',
|
||||
|
||||
send_title: 'ETHを送信',
|
||||
send_description: '支払いを送信',
|
||||
|
||||
|
@ -302,13 +197,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: '残高に十分なETHがありません('
|
||||
},
|
||||
ko: {
|
||||
location_title: '위치',
|
||||
location_description: '내 위치 공유하기',
|
||||
location_address: '주소',
|
||||
|
||||
browse_title: '브라우저',
|
||||
browse_description: '브라우저 시작하기',
|
||||
|
||||
send_title: 'ETH 보내기',
|
||||
send_description: '지불금 보내기',
|
||||
|
||||
|
@ -322,13 +210,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH 잔고가 부족합니다 ('
|
||||
},
|
||||
pl: {
|
||||
location_title: 'Lokalizacja',
|
||||
location_description: 'Udostępnij swoją lokalizację',
|
||||
location_address: 'Adres',
|
||||
|
||||
browse_title: 'Przeglądarka',
|
||||
browse_description: 'Uruchom przeglądarkę',
|
||||
|
||||
send_title: 'Wyślij ETH',
|
||||
send_description: 'Wyślij płatność',
|
||||
|
||||
|
@ -342,13 +223,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Brak wystarczającej liczby ETH na koncie ('
|
||||
},
|
||||
'pt-br': {
|
||||
location_title: 'Localização',
|
||||
location_description: 'Compartilhar sua localização',
|
||||
location_address: 'Endereço',
|
||||
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Abrir o navegador',
|
||||
|
||||
send_title: 'Enviar ETH',
|
||||
send_description: 'Enviar um pagamento',
|
||||
|
||||
|
@ -362,13 +236,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH insuficiente no saldo ('
|
||||
},
|
||||
'pt-pt': {
|
||||
location_title: 'Location',
|
||||
location_description: 'Partilhar a sua localização',
|
||||
location_address: 'Endereço',
|
||||
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Abrir o navegador',
|
||||
|
||||
send_title: 'Enviar ETH',
|
||||
send_description: 'Enviar um pagamento',
|
||||
|
||||
|
@ -382,13 +249,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Não há ETH suficiente no saldo ('
|
||||
},
|
||||
ro: {
|
||||
location_title: 'Locație',
|
||||
location_description: "Partajează locația",
|
||||
location_address: 'Adresă',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Lansare browser',
|
||||
|
||||
send_title: 'Trimite ETH',
|
||||
send_description: 'Trimite o plată',
|
||||
|
||||
|
@ -402,13 +262,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Sold ETH insuficient ('
|
||||
},
|
||||
sl: {
|
||||
location_title: 'Lokacija',
|
||||
location_description: 'Deli svojo lokacijo',
|
||||
location_address: 'Naslov',
|
||||
|
||||
browse_title: 'Brskalnik',
|
||||
browse_description: 'Zaženi brskalnik',
|
||||
|
||||
send_title: 'Pošlji ETH',
|
||||
send_description: 'Pošlji plačilo',
|
||||
|
||||
|
@ -422,13 +275,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Stanje ETH na računu je prenizko ('
|
||||
},
|
||||
es: {
|
||||
location_title: 'Ubicación',
|
||||
location_description: 'Comparte tu ubicación',
|
||||
location_address: 'Dirección',
|
||||
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Iniciar el navegador',
|
||||
|
||||
send_title: 'Enviar ETH ',
|
||||
send_description: 'Enviar un pago',
|
||||
|
||||
|
@ -442,13 +288,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'No hay suficiente ETH en conjunto ('
|
||||
},
|
||||
'es-ar': {
|
||||
location_title: 'Ubicación',
|
||||
location_description: 'Comparte tu ubicación',
|
||||
location_address: 'Dirección',
|
||||
|
||||
browse_title: 'Navegador',
|
||||
browse_description: 'Iniciar navegador',
|
||||
|
||||
send_title: 'Enviar ETH',
|
||||
send_description: 'Enviar un pago',
|
||||
|
||||
|
@ -462,13 +301,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'No tienes suficiente ETH en tu saldo ('
|
||||
},
|
||||
sw: {
|
||||
location_title: 'Eneo',
|
||||
location_description: 'Shiriki eneo lako',
|
||||
location_address: 'Anwani',
|
||||
|
||||
browse_title: 'Programu ya utafutaji',
|
||||
browse_description: 'Zindua programu ya utafutaji',
|
||||
|
||||
send_title: 'Tuma ETH',
|
||||
send_description: 'Tuma malipo',
|
||||
|
||||
|
@ -482,13 +314,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH haitoshi kwenye salio ('
|
||||
},
|
||||
sv: {
|
||||
location_title: 'Plats',
|
||||
location_description: 'Dela din plats',
|
||||
location_address: 'Adress',
|
||||
|
||||
browse_title: 'Webbläsare',
|
||||
browse_description: 'Starta webbläsaren',
|
||||
|
||||
send_title: 'Skicka ETH',
|
||||
send_description: 'Skicka en betalning',
|
||||
|
||||
|
@ -502,13 +327,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Inte tillräcklig ETH på balansen ('
|
||||
},
|
||||
'fr-ch': {
|
||||
location_title: 'Emplacement',
|
||||
location_description: 'Partagez votre emplacement',
|
||||
location_address: 'Adresse',
|
||||
|
||||
browse_title: 'Navigateur',
|
||||
browse_description: 'Lancer le navigateur',
|
||||
|
||||
send_title: 'Envoyer des ETH',
|
||||
send_description: 'Envoyer un paiement',
|
||||
|
||||
|
@ -522,13 +340,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Pas assez d\'ETH sur le solde ('
|
||||
},
|
||||
'de-ch': {
|
||||
location_title: 'Standort',
|
||||
location_description: 'Teile deinen Standort',
|
||||
location_address: 'Adresse',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Starte den Browser',
|
||||
|
||||
send_title: 'Sende ETH',
|
||||
send_description: 'Sende eine Zahlung',
|
||||
|
||||
|
@ -542,13 +353,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Nicht genug ETH vorhanden ('
|
||||
},
|
||||
'it-ch': {
|
||||
location_title: 'Posizione',
|
||||
location_description: 'Condividi la tua posizione',
|
||||
location_address: 'Indirizzo',
|
||||
|
||||
browse_title: 'Browser',
|
||||
browse_description: 'Avvia il browser',
|
||||
|
||||
send_title: 'Invia ETH',
|
||||
send_description: 'Invia un pagamento',
|
||||
|
||||
|
@ -562,13 +366,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Saldo ETH non sufficiente ('
|
||||
},
|
||||
th: {
|
||||
location_title: 'ตำแหน่ง',
|
||||
location_description: 'แชร์ตำแหน่งของคุณ',
|
||||
location_address: 'ที่อยู่',
|
||||
|
||||
browse_title: 'เบราว์เซอร์',
|
||||
browse_description: 'เปิดเบราว์เซอร์',
|
||||
|
||||
send_title: 'ส่ง ETH',
|
||||
send_description: 'ส่งการชำระเงิน',
|
||||
|
||||
|
@ -582,13 +379,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'มี ETH ไม่เพียงพอในยอดคงเหลือ ('
|
||||
},
|
||||
tr: {
|
||||
location_title: 'Konum',
|
||||
location_description: 'Konumunuzu paylaşın',
|
||||
location_address: 'Adres',
|
||||
|
||||
browse_title: 'Tarayıcı',
|
||||
browse_description: 'Tarayıcıyı başlat',
|
||||
|
||||
send_title: 'ETH gönder',
|
||||
send_description: 'Bir ödeme gönder',
|
||||
|
||||
|
@ -601,14 +391,7 @@ I18n.translations = {
|
|||
validation_invalid_number: 'Miktar geçerli bir sayı değil',
|
||||
validation_insufficient_amount: 'Yeterli ETH bakiyesi yok ('
|
||||
},
|
||||
uk: {
|
||||
location_title: 'Місцезнаходження',
|
||||
location_description: 'Поділіться своїм місцезнаходженням',
|
||||
location_address: 'Адреса',
|
||||
|
||||
browse_title: 'Браузер',
|
||||
browse_description: 'Запустити браузер',
|
||||
|
||||
uk: {
|
||||
send_title: 'Надіслати ETH',
|
||||
send_description: 'Надіслати платіж',
|
||||
|
||||
|
@ -622,13 +405,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Не вистачає ETH на балансі ('
|
||||
},
|
||||
ur: {
|
||||
location_title: 'مقام',
|
||||
location_description: 'اپنا مقام بتائیں',
|
||||
location_address: 'پتہ',
|
||||
|
||||
browse_title: 'براؤزر',
|
||||
browse_description: 'براؤزر کھولیں',
|
||||
|
||||
send_title: 'ETH بھیجیں',
|
||||
send_description: 'ادائیگی کریں',
|
||||
|
||||
|
@ -642,13 +418,6 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'ETH میں کافی بیلنس نہیں ہے ('
|
||||
},
|
||||
vi: {
|
||||
location_title: 'Vị trí',
|
||||
location_description: 'Chia sẻ vị trí của bạn',
|
||||
location_address: 'Địa chỉ',
|
||||
|
||||
browse_title: 'Trình duyệt',
|
||||
browse_description: 'Mở trình duyệt',
|
||||
|
||||
send_title: 'Gửi ETH',
|
||||
send_description: 'Gửi một khoản thanh toán',
|
||||
|
||||
|
@ -662,295 +431,3 @@ I18n.translations = {
|
|||
validation_insufficient_amount: 'Không đủ ETH trong số dư ('
|
||||
}
|
||||
};
|
||||
|
||||
status.command({
|
||||
name: "location",
|
||||
icon: "location",
|
||||
title: I18n.t('location_title'),
|
||||
description: I18n.t('location_description'),
|
||||
color: "#a187d5",
|
||||
sequentialParams: true,
|
||||
preview: function (params) {
|
||||
var text = status.components.text(
|
||||
{
|
||||
style: {
|
||||
marginTop: 5,
|
||||
marginHorizontal: 0,
|
||||
fontSize: 14,
|
||||
fontFamily: "font",
|
||||
color: "black"
|
||||
}
|
||||
}, params.address);
|
||||
var uri = "https://maps.googleapis.com/maps/api/staticmap?center="
|
||||
+ params.address
|
||||
+ "&size=100x100&maptype=roadmap&key=AIzaSyBNsj1qoQEYPb3IllmWMAscuXW0eeuYqAA&language=en"
|
||||
+ "&markers=size:mid%7Ccolor:0xff0000%7Clabel:%7C"
|
||||
+ params.address;
|
||||
|
||||
var image = status.components.image(
|
||||
{
|
||||
source: {uri: uri},
|
||||
style: {
|
||||
width: 100,
|
||||
height: 100
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return {markup: status.components.view({}, [text, image])};
|
||||
},
|
||||
shortPreview: function (params) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('location_title') + ": " + params.address
|
||||
)
|
||||
};
|
||||
}
|
||||
}).param({
|
||||
name: "address",
|
||||
type: status.types.TEXT,
|
||||
placeholder: I18n.t('location_address')
|
||||
});
|
||||
|
||||
status.command({
|
||||
name: "browse",
|
||||
fullscreen: true,
|
||||
title: I18n.t('browse_title'),
|
||||
description: I18n.t('browse_description'),
|
||||
params: [{
|
||||
name: "url",
|
||||
placeholder: "URL",
|
||||
type: status.types.TEXT
|
||||
}],
|
||||
onSend: function (params, context) {
|
||||
var url = params.url;
|
||||
if (!/^[a-zA-Z-_]+:/.test(url)) {
|
||||
url = 'http://' + url;
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Browser",
|
||||
dynamicTitle: true,
|
||||
markup: status.components.bridgedWebView(url)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function validateSend(params, context) {
|
||||
if (!context.to) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
"Wrong address",
|
||||
"Recipient address must be specified"
|
||||
)
|
||||
};
|
||||
}
|
||||
if (!params.amount) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_amount_specified')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
var amount = params.amount.replace(",", ".");
|
||||
var amountSplitted = amount.split(".");
|
||||
if (amountSplitted.length === 2 && amountSplitted[1].length > 18) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_amount_is_too_small')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
var val = web3.toWei(amount, "ether");
|
||||
if (val <= 0) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_invalid_number')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
var balance = web3.eth.getBalance(context.from);
|
||||
var estimatedGas = web3.eth.estimateGas({
|
||||
from: context.from,
|
||||
to: context.to,
|
||||
value: val
|
||||
});
|
||||
|
||||
if (bn(val).plus(bn(estimatedGas)).greaterThan(bn(balance))) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_insufficient_amount')
|
||||
+ web3.fromWei(balance, "ether")
|
||||
+ " ETH)"
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function sendTransaction(params, context) {
|
||||
var data = {
|
||||
from: context.from,
|
||||
to: context.to,
|
||||
value: web3.toWei(params.amount.replace(",", "."), "ether")
|
||||
};
|
||||
|
||||
try {
|
||||
return web3.eth.sendTransaction(data);
|
||||
} catch (err) {
|
||||
return {error: err.message};
|
||||
}
|
||||
}
|
||||
|
||||
var send = {
|
||||
name: "send",
|
||||
icon: "money_white",
|
||||
color: "#5fc48d",
|
||||
title: I18n.t('send_title'),
|
||||
description: I18n.t('send_description'),
|
||||
sequentialParams: true,
|
||||
params: [{
|
||||
name: "amount",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
preview: function (params, context) {
|
||||
var amountStyle = {
|
||||
fontSize: 36,
|
||||
color: "#000000",
|
||||
height: 40
|
||||
};
|
||||
|
||||
var amount = status.components.view(
|
||||
{
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
[status.components.text(
|
||||
{
|
||||
style: amountStyle,
|
||||
font: "light"
|
||||
},
|
||||
status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
)]);
|
||||
|
||||
var currency = status.components.view(
|
||||
{
|
||||
style: {
|
||||
flexDirection: "column",
|
||||
justifyContent: "flex-end",
|
||||
paddingBottom: 0
|
||||
}
|
||||
},
|
||||
[status.components.text(
|
||||
{
|
||||
style: {
|
||||
color: "#9199a0",
|
||||
fontSize: 16,
|
||||
lineHeight: 18,
|
||||
marginLeft: 7.5
|
||||
}
|
||||
},
|
||||
"ETH"
|
||||
)]
|
||||
);
|
||||
|
||||
return {
|
||||
markup: status.components.view(
|
||||
{
|
||||
style: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
marginTop: 8,
|
||||
marginBottom: 8
|
||||
}
|
||||
},
|
||||
[amount, currency]
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('send_title') + ": "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
handler: sendTransaction,
|
||||
validator: validateSend
|
||||
};
|
||||
|
||||
status.command(send);
|
||||
status.response(send);
|
||||
|
||||
status.command({
|
||||
name: "request",
|
||||
color: "#5fc48d",
|
||||
title: I18n.t('request_title'),
|
||||
description: I18n.t('request_description'),
|
||||
sequentialParams: true,
|
||||
params: [{
|
||||
name: "amount",
|
||||
type: status.types.NUMBER
|
||||
}],
|
||||
handler: function (params) {
|
||||
return {
|
||||
event: "request",
|
||||
params: [params.amount],
|
||||
request: {
|
||||
command: "send",
|
||||
params: {
|
||||
amount: params.amount
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
preview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('request_requesting') + " "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
shortPreview: function (params, context) {
|
||||
return {
|
||||
markup: status.components.text(
|
||||
{},
|
||||
I18n.t('request_requesting') + " "
|
||||
+ status.localizeNumber(params.amount, context.delimiter, context.separator)
|
||||
+ " ETH"
|
||||
)
|
||||
};
|
||||
},
|
||||
validator: function (params) {
|
||||
try {
|
||||
var val = web3.toWei(params.amount.replace(",", "."), "ether");
|
||||
if (val <= 0) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
markup: status.components.validationMessage(
|
||||
I18n.t('validation_title'),
|
||||
I18n.t('validation_invalid_number')
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
|
@ -42,7 +42,7 @@
|
|||
[]
|
||||
(ra/stop-figwheel!))
|
||||
|
||||
(hawk/watch! [{:paths ["resources"]
|
||||
(hawk/watch! [{:paths ["resources" "bots"]
|
||||
:handler (fn [ctx e]
|
||||
(let [path "src/status_im/utils/js_resources.cljs"
|
||||
js-resourced (slurp path)]
|
||||
|
|
1937
resources/console.js
1937
resources/console.js
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,35 @@
|
|||
"photo-path": "icon_wallet_avatar",
|
||||
"add-chat?": true,
|
||||
"dapp?": true,
|
||||
"groups": ["dapps"]
|
||||
"groups": ["dapps"],
|
||||
"has-global-command?": true,
|
||||
"dapp-url":
|
||||
{
|
||||
"en": "https://status.im/dapps/wallet/"
|
||||
},
|
||||
"bot-url": "local://wallet-bot"
|
||||
},
|
||||
|
||||
"mailman":
|
||||
{
|
||||
"name":
|
||||
{
|
||||
"en": "Mailman",
|
||||
"ru": "Печкин"
|
||||
},
|
||||
"dapp?": true,
|
||||
"has-global-command?": true,
|
||||
"bot-url": "local://mailman-bot"
|
||||
},
|
||||
|
||||
"browse":
|
||||
{
|
||||
"name":
|
||||
{
|
||||
"en": "Browse"
|
||||
},
|
||||
"dapp?": true,
|
||||
"bot-url": "local://browse-bot"
|
||||
},
|
||||
|
||||
"0x0428c9d6c1aaaa8369a7c63819684f30e34396dc0907d49afeac85a0a774ccb919b3482097d992e66bcc538e7a0c6acf874c77748f396f53c0a102e10d1a37765b":
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,31 +0,0 @@
|
|||
status.command({
|
||||
name: "browse",
|
||||
title: I18n.t('browse_title'),
|
||||
description: I18n.t('browse_description'),
|
||||
color: "#ffa500",
|
||||
fullscreen: true,
|
||||
onSend: function (params, context) {
|
||||
var url = 'https://status.im/dapps/wallet';
|
||||
if (context.debug) {
|
||||
url = 'http://127.0.0.1:3450';
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Wallet",
|
||||
dynamicTitle: false,
|
||||
markup: status.components.bridgedWebView(url)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
status.autorun("browse");
|
||||
|
||||
status.registerFunction("send", function (params, context) {
|
||||
var data = {
|
||||
from: context.from,
|
||||
to: params.address,
|
||||
value: web3.toWei(params.amount, "ether")
|
||||
};
|
||||
|
||||
web3.eth.sendTransaction(data);
|
||||
})
|
|
@ -33,9 +33,8 @@
|
|||
[view st/account-view
|
||||
[account-bage address photo-path name]]]])
|
||||
|
||||
(defn- create-account [_]
|
||||
(dispatch-sync [:reset-app])
|
||||
(dispatch [:navigate-to :chat console-chat-id]))
|
||||
(defn create-account [_]
|
||||
(dispatch [:reset-app #(dispatch [:navigate-to :chat console-chat-id])]))
|
||||
|
||||
(defview accounts []
|
||||
[accounts [:get :accounts]]
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
(def spacing-char " ")
|
||||
(def arg-wrapping-char "\"")
|
||||
(def masking-char "*")
|
||||
(def bot-char "@")
|
||||
|
||||
(def input-height 56)
|
||||
(def max-input-height 66)
|
||||
|
|
|
@ -176,6 +176,9 @@
|
|||
(doseq [{:keys [content] :as message} messages]
|
||||
(when (and (:command content)
|
||||
(not (:content content)))
|
||||
;; todo rewrite it so that commands defined outside chat's context
|
||||
;; (bots' commands in group chats and global commands in all chats)
|
||||
;; could be rendered properly
|
||||
(dispatch [:request-command-data (assoc message :chat-id current-chat-id)])))
|
||||
(assoc db :messages messages))))
|
||||
|
||||
|
|
|
@ -12,25 +12,26 @@
|
|||
(handlers/side-effect!
|
||||
(fn [{:keys [chats current-account-id] :as db}
|
||||
[_ {{:keys [command params content-command type]} :content
|
||||
:keys [message-id chat-id on-requested] :as message} data-type]]
|
||||
(if-not (get-in chats [chat-id :commands-loaded])
|
||||
(do (dispatch [:add-commands-loading-callback
|
||||
chat-id
|
||||
#(dispatch [:request-command-data message data-type])])
|
||||
(dispatch [:load-commands! chat-id]))
|
||||
(let [path [(if (= :response (keyword type)) :responses :commands)
|
||||
(if content-command content-command command)
|
||||
data-type]
|
||||
to (get-in db [:contacts chat-id :address])
|
||||
params {:parameters params
|
||||
:context (merge {:platform platform/platform
|
||||
:from current-account-id
|
||||
:to to}
|
||||
i18n/delimeters)}
|
||||
callback #(let [result (get-in % [:result :returned])
|
||||
result (if (:markup result)
|
||||
(update result :markup cu/generate-hiccup)
|
||||
result)]
|
||||
(dispatch [:set-in [:message-data data-type message-id] result])
|
||||
(when on-requested (on-requested result)))]
|
||||
(status/call-jail chat-id path params callback))))))
|
||||
:keys [message-id chat-id on-requested jail-id] :as message} data-type]]
|
||||
(let [jail-id (or jail-id chat-id)]
|
||||
(if-not (get-in chats [jail-id :commands-loaded])
|
||||
(do (dispatch [:add-commands-loading-callback
|
||||
jail-id
|
||||
#(dispatch [:request-command-data message data-type])])
|
||||
(dispatch [:load-commands! jail-id]))
|
||||
(let [path [(if (= :response (keyword type)) :responses :commands)
|
||||
(if content-command content-command command)
|
||||
data-type]
|
||||
to (get-in db [:contacts chat-id :address])
|
||||
params {:parameters params
|
||||
:context (merge {:platform platform/platform
|
||||
:from current-account-id
|
||||
:to to}
|
||||
i18n/delimeters)}
|
||||
callback #(let [result (get-in % [:result :returned])
|
||||
result (if (:markup result)
|
||||
(update result :markup cu/generate-hiccup)
|
||||
result)]
|
||||
(dispatch [:set-in [:message-data data-type message-id] result])
|
||||
(when on-requested (on-requested result)))]
|
||||
(status/call-jail jail-id path params callback)))))))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:require [re-frame.core :refer [enrich after dispatch]]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.chat.utils :as chat-utils]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.suggestions :as suggestions]
|
||||
[status-im.components.react :as react-comp]
|
||||
|
@ -38,9 +39,8 @@
|
|||
:select-chat-input-command
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id chat-ui-props] :as db}
|
||||
[_ {:keys [name prefill sequential-params] :as command} metadata]]
|
||||
(dispatch [:set-chat-input-text (str const/command-char
|
||||
name
|
||||
[_ {:keys [prefill sequential-params] :as command} metadata]]
|
||||
(dispatch [:set-chat-input-text (str (chat-utils/command-name command)
|
||||
const/spacing-char
|
||||
(when-not sequential-params
|
||||
(input-model/join-command-args prefill)))])
|
||||
|
@ -66,10 +66,10 @@
|
|||
:set-command-argument
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id] :as db} [_ [index arg]]]
|
||||
(let [command (-> (get-in db [:chats current-chat-id :input-text])
|
||||
(input-model/split-command-args))
|
||||
seq-params? (-> (input-model/selected-chat-command db current-chat-id)
|
||||
(get-in [:command :sequential-params]))]
|
||||
(let [command (-> (get-in db [:chats current-chat-id :input-text])
|
||||
(input-model/split-command-args))
|
||||
seq-params? (-> (input-model/selected-chat-command db current-chat-id)
|
||||
(get-in [:command :sequential-params]))]
|
||||
(if seq-params?
|
||||
(dispatch [:set-chat-seq-arg-input-text arg])
|
||||
(let [command-name (first command)
|
||||
|
@ -95,16 +95,17 @@
|
|||
(handlers/register-handler
|
||||
:update-suggestions
|
||||
(fn [{:keys [current-chat-id] :as db} [_ chat-id text]]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
chat-text (or text (get-in db [:chats chat-id :input-text]) "")
|
||||
requests (suggestions/get-request-suggestions db chat-text)
|
||||
suggestions (suggestions/get-command-suggestions db chat-text)
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
chat-text (or text (get-in db [:chats chat-id :input-text]) "")
|
||||
requests (suggestions/get-request-suggestions db chat-text)
|
||||
suggestions (suggestions/get-command-suggestions db chat-text)
|
||||
global-commands (suggestions/get-global-command-suggestions db chat-text)
|
||||
{:keys [dapp?]} (get-in db [:contacts chat-id])]
|
||||
(when (and dapp? (empty? (into requests suggestions)))
|
||||
(when (and dapp? (every? empty? [requests suggestions global-commands]))
|
||||
(dispatch [::check-dapp-suggestions chat-id chat-text]))
|
||||
(-> db
|
||||
(assoc-in [:chats chat-id :request-suggestions] requests)
|
||||
(assoc-in [:chats chat-id :command-suggestions] suggestions)))))
|
||||
(assoc-in [:chats chat-id :command-suggestions] (into suggestions global-commands))))))
|
||||
|
||||
(handlers/register-handler
|
||||
:load-chat-parameter-box
|
||||
|
@ -137,12 +138,12 @@
|
|||
::send-message
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-public-key current-account-id] :as db} [_ command-message chat-id]]
|
||||
(let [text (get-in db [:chats chat-id :input-text])
|
||||
data {:message text
|
||||
:command command-message
|
||||
:chat-id chat-id
|
||||
:identity current-public-key
|
||||
:address current-account-id}]
|
||||
(let [text (get-in db [:chats chat-id :input-text])
|
||||
data {:message text
|
||||
:command command-message
|
||||
:chat-id chat-id
|
||||
:identity current-public-key
|
||||
:address current-account-id}]
|
||||
(dispatch [:set-chat-input-text nil chat-id])
|
||||
(dispatch [:set-chat-input-metadata nil chat-id])
|
||||
(dispatch [:set-chat-ui-props {:sending-in-progress? false}])
|
||||
|
@ -156,18 +157,28 @@
|
|||
:proceed-command
|
||||
(handlers/side-effect!
|
||||
(fn [db [_ command chat-id]]
|
||||
(let [after-validation #(dispatch [::request-command-data
|
||||
{:command command
|
||||
:chat-id chat-id
|
||||
:data-type :on-send
|
||||
:after (fn [_ res]
|
||||
(dispatch [::send-command res command chat-id]))}])]
|
||||
(dispatch [::request-command-data
|
||||
{:command command
|
||||
:chat-id chat-id
|
||||
:data-type :validator
|
||||
:after #(dispatch [::proceed-validation-messages
|
||||
command chat-id %2 after-validation])}])))))
|
||||
(let [jail-id (or (get-in command [:command :bot]) chat-id)]
|
||||
;:check-and-load-commands!
|
||||
(let [params
|
||||
{:command command
|
||||
:chat-id jail-id}
|
||||
|
||||
on-send-params
|
||||
(merge params
|
||||
{:data-type :on-send
|
||||
:after (fn [_ res]
|
||||
(dispatch [::send-command res command chat-id]))})
|
||||
|
||||
after-validation
|
||||
#(dispatch [::request-command-data on-send-params])
|
||||
|
||||
validation-params
|
||||
(merge params
|
||||
{:data-type :validator
|
||||
:after #(dispatch [::proceed-validation-messages
|
||||
command chat-id %2 after-validation])})]
|
||||
|
||||
(dispatch [::request-command-data validation-params]))))))
|
||||
|
||||
(handlers/register-handler
|
||||
::proceed-validation-messages
|
||||
|
@ -215,7 +226,7 @@
|
|||
(handlers/side-effect!
|
||||
(fn [{:keys [contacts] :as db}
|
||||
[_ {{:keys [command metadata args] :as c} :command
|
||||
:keys [message-id chat-id data-type after]}]]
|
||||
:keys [message-id chat-id data-type after]}]]
|
||||
(let [{:keys [dapp? dapp-url name]} (get contacts chat-id)
|
||||
message-id (random/id)
|
||||
metadata (merge metadata
|
||||
|
@ -228,7 +239,8 @@
|
|||
:to-message (:to-message-id metadata)
|
||||
:created-at (time/now-ms)
|
||||
:id message-id
|
||||
:chat-id chat-id}
|
||||
:chat-id chat-id
|
||||
:jail-id (or (:bot command) chat-id)}
|
||||
request-data {:message-id message-id
|
||||
:chat-id chat-id
|
||||
:content {:command (:name command)
|
||||
|
|
|
@ -127,21 +127,25 @@
|
|||
(fn [db [_ {:keys [chat-id address command-message]
|
||||
:as parameters}]]
|
||||
(let [{:keys [id command params]} command-message
|
||||
{:keys [type name]} command
|
||||
path [(if (= :command type) :commands :responses)
|
||||
name
|
||||
:handler]
|
||||
to (get-in db [:contacts chat-id :address])
|
||||
params {:parameters params
|
||||
:context {:from address
|
||||
:to to
|
||||
:message-id id}}]
|
||||
(status/call-jail
|
||||
chat-id
|
||||
path
|
||||
params
|
||||
(fn [result]
|
||||
(dispatch [:command-handler! chat-id parameters result])))))))
|
||||
{:keys [type name bot]} command
|
||||
path [(if (= :command type) :commands :responses)
|
||||
name
|
||||
:handler]
|
||||
to (get-in db [:contacts chat-id :address])
|
||||
params {:parameters params
|
||||
:context {:from address
|
||||
:to to
|
||||
:message-id id}}
|
||||
identity (or bot chat-id)]
|
||||
(dispatch
|
||||
[:check-and-load-commands!
|
||||
identity
|
||||
#(status/call-jail
|
||||
identity
|
||||
path
|
||||
params
|
||||
(fn [res]
|
||||
(dispatch [:command-handler! chat-id parameters res])))])))))
|
||||
|
||||
(register-handler :prepare-message
|
||||
(u/side-effect!
|
||||
|
|
|
@ -5,17 +5,18 @@
|
|||
[status-im.chat.views.input.validation-messages :refer [validation-message]]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.phone-number :as phone-number]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.utils :as chat-utils]))
|
||||
|
||||
(defn text-ends-with-space? [text]
|
||||
(when text
|
||||
(= (str/last-index-of text const/spacing-char)
|
||||
(dec (count text)))))
|
||||
|
||||
(defn possible-chat-actions [db chat-id]
|
||||
(defn possible-chat-actions [{:keys [global-commands] :as db} chat-id]
|
||||
(let [{:keys [commands requests responses]} (get-in db [:chats chat-id])
|
||||
|
||||
commands' (into {} (map (fn [[k v]] [k [v :any]]) commands))
|
||||
commands' (into {} (map (fn [[k v]] [k [v :any]]) (merge global-commands commands)))
|
||||
responses' (into {} (map (fn [{:keys [message-id type]}]
|
||||
[type [(get responses type) message-id]])
|
||||
requests))]
|
||||
|
@ -60,9 +61,9 @@
|
|||
possible-actions (possible-chat-actions db chat-id)
|
||||
command-args (split-command-args input-text)
|
||||
command-name (first command-args)]
|
||||
(when (.startsWith (or command-name "") const/command-char)
|
||||
(when-let [[command to-message-id] (-> (filter (fn [[{:keys [name]} message-id]]
|
||||
(= name (subs command-name 1)))
|
||||
(when (chat-utils/starts-as-command? (or command-name ""))
|
||||
(when-let [[command to-message-id] (-> (filter (fn [[{:keys [name bot]} message-id]]
|
||||
(= (or bot name) (subs command-name 1)))
|
||||
possible-actions)
|
||||
(first))]
|
||||
{:command command
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
(:require [status-im.chat.constants :as chat-consts]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn suggestion? [text]
|
||||
(= (get text 0) chat-consts/command-char))
|
||||
(defn can-be-suggested?
|
||||
([text] (can-be-suggested? chat-consts/command-char :name text))
|
||||
([first-char name-key text]
|
||||
(fn [command]
|
||||
(let [name (get command name-key)]
|
||||
(let [text' (cond
|
||||
(.startsWith text first-char)
|
||||
text
|
||||
|
||||
(defn can-be-suggested? [text]
|
||||
(fn [{:keys [name]}]
|
||||
(let [text' (cond
|
||||
(.startsWith text chat-consts/command-char)
|
||||
text
|
||||
(str/blank? text)
|
||||
first-char
|
||||
|
||||
(str/blank? text)
|
||||
chat-consts/command-char
|
||||
|
||||
:default
|
||||
nil)]
|
||||
(.startsWith (str chat-consts/command-char name) text'))))
|
||||
:default
|
||||
nil)]
|
||||
(.startsWith (str first-char name) text'))))))
|
||||
|
||||
(defn get-request-suggestions
|
||||
[{:keys [current-chat-id] :as db} text]
|
||||
|
@ -30,3 +30,8 @@
|
|||
[{:keys [current-chat-id] :as db} text]
|
||||
(let [commands (get-in db [:chats current-chat-id :commands])]
|
||||
(filter (fn [[_ v]] ((can-be-suggested? text) v)) commands)))
|
||||
|
||||
(defn get-global-command-suggestions
|
||||
[{:keys [global-commands] :as db} text]
|
||||
(filter (fn [[_ v]] ((can-be-suggested? chat-consts/bot-char :bot text) v))
|
||||
global-commands))
|
||||
|
|
|
@ -183,6 +183,5 @@
|
|||
:name (s/capitalize console-chat-id)
|
||||
:photo-path console-chat-id
|
||||
:dapp? true
|
||||
; todo remove/change dapp config fot console
|
||||
:dapp-url "http://localhost:8185/resources"
|
||||
:bot-url "local://console-bot"
|
||||
:dapp-hash 858845357})
|
||||
|
|
|
@ -54,8 +54,12 @@
|
|||
(fn [_ [_ chat-id]]
|
||||
(reaction (chats/get-by-id chat-id))))
|
||||
|
||||
(register-sub
|
||||
:get-commands
|
||||
(register-sub :get-bots-suggestions
|
||||
(fn [db _]
|
||||
(let [chat-id (subscribe [:get-current-chat-id])]
|
||||
(reaction (get-in @db [:bots-suggestions @chat-id])))))
|
||||
|
||||
(register-sub :get-commands
|
||||
(fn [db [_ chat-id]]
|
||||
(let [current-chat (or chat-id (@db :current-chat-id))]
|
||||
(reaction (or (get-in @db [:chats current-chat :commands]) {})))))
|
||||
|
@ -138,8 +142,7 @@
|
|||
requests (subscribe [:chat :request-suggestions chat-id])
|
||||
commands (subscribe [:chat :command-suggestions chat-id])]
|
||||
(reaction
|
||||
(and (or @show-suggestions?
|
||||
(.startsWith (or @input-text "") const/command-char))
|
||||
(and (or @show-suggestions? (chat-utils/starts-as-command? @input-text))
|
||||
(not (:command @selected-command))
|
||||
(or (not-empty @requests)
|
||||
(not-empty @commands)))))))
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns status-im.chat.utils
|
||||
(:require [status-im.constants :refer [console-chat-id
|
||||
wallet-chat-id]]
|
||||
[clojure.string :as str]))
|
||||
[clojure.string :as str]
|
||||
[status-im.chat.constants :as const]))
|
||||
|
||||
(defn console? [s]
|
||||
(= console-chat-id s))
|
||||
|
@ -45,3 +46,13 @@
|
|||
(if validator
|
||||
(validator message)
|
||||
(pos? (count message))))
|
||||
|
||||
(defn command-name [{:keys [bot name]}]
|
||||
(if bot
|
||||
(str const/bot-char bot)
|
||||
(str const/command-char name)))
|
||||
|
||||
(defn starts-as-command? [text]
|
||||
(and (not (nil? text))
|
||||
(or (str/starts-with? text const/bot-char)
|
||||
(str/starts-with? text const/command-char))))
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
[status-im.chat.constants :as const]
|
||||
[status-im.components.animation :as anim]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.chat.utils :as chat-utils]))
|
||||
|
||||
(defn command-view [first? {command-name :name :as command}]
|
||||
(defn command-view [first? command]
|
||||
[touchable-highlight {:on-press #(dispatch [:select-chat-input-command command nil])}
|
||||
[view
|
||||
[text {:style (style/command first?)
|
||||
:font :roboto-mono}
|
||||
(str const/command-char) command-name]]])
|
||||
(chat-utils/command-name command)]]])
|
||||
|
||||
(defview commands-view []
|
||||
[commands [:chat :command-suggestions]
|
||||
|
@ -117,7 +118,7 @@
|
|||
(when-not (get-in command [:command :sequential-params])
|
||||
(let [real-args (remove str/blank? (:args command))]
|
||||
(when-let [placeholder (cond
|
||||
(= @input-text const/command-char)
|
||||
(#{const/command-char const/bot-char} @input-text)
|
||||
(i18n/label :t/type-a-command)
|
||||
|
||||
(and command (empty? real-args))
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
[status-im.chat.views.input.animations.expandable :refer [expandable-view]]
|
||||
[status-im.chat.views.input.utils :as input-utils]
|
||||
[status-im.i18n :refer [label]]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.utils :as chat-utils]))
|
||||
|
||||
(defn suggestion-item [{:keys [on-press name description last?]}]
|
||||
[touchable-highlight {:on-press on-press}
|
||||
[view (style/item-suggestion-container last?)
|
||||
[view {:style style/item-suggestion-name}
|
||||
[text {:style style/item-suggestion-name-text
|
||||
:font :roboto-mono}
|
||||
const/command-char name]]
|
||||
:font :roboto-mono} name]]
|
||||
[text {:style style/item-suggestion-description
|
||||
:number-of-lines 2}
|
||||
description]]])
|
||||
|
@ -36,11 +36,10 @@
|
|||
:description description
|
||||
:last? last?}])
|
||||
|
||||
(defview command-item [{:keys [name description] :as command} last?]
|
||||
[]
|
||||
(defn command-item [{:keys [name description bot] :as command} last?]
|
||||
[suggestion-item
|
||||
{:on-press #(dispatch [:select-chat-input-command command nil])
|
||||
:name name
|
||||
:name (chat-utils/command-name command)
|
||||
:description description
|
||||
:last? last?}])
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[status-im.utils.utils :refer [http-get show-popup]]
|
||||
[clojure.string :as s]
|
||||
[status-im.data-store.commands :as commands]
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.components.status :as status]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
[status-im.commands.utils :refer [reg-handler]]
|
||||
|
@ -12,33 +13,33 @@
|
|||
[status-im.i18n :refer [label]]
|
||||
[status-im.utils.homoglyph :as h]
|
||||
[status-im.utils.js-resources :as js-res]
|
||||
[status-im.utils.random :as random]))
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.chat.sign-up :as sign-up]))
|
||||
|
||||
(def commands-js "commands.js")
|
||||
|
||||
(defn load-commands!
|
||||
[{:keys [current-chat-id contacts]} [identity]]
|
||||
(let [identity (or identity current-chat-id)
|
||||
contact (or (get contacts identity)
|
||||
{:whisper-identity identity})]
|
||||
(when identity
|
||||
(dispatch [::fetch-commands! contact])))
|
||||
[{:keys [current-chat-id contacts]} [identity callback]]
|
||||
(let [identity' (or identity current-chat-id)
|
||||
contact (or (get contacts identity')
|
||||
sign-up/console-contact)]
|
||||
(when identity'
|
||||
(dispatch [::fetch-commands! {:contact contact
|
||||
:callback callback}])))
|
||||
;; todo uncomment
|
||||
#_(if-let [{:keys [file]} (commands/get-by-chat-id identity)]
|
||||
(dispatch [::parse-commands! identity file])
|
||||
(dispatch [::fetch-commands! identity])))
|
||||
|
||||
(defn fetch-commands!
|
||||
[_ [{:keys [whisper-identity dapp? dapp-url]}]]
|
||||
[_ [{{:keys [dapp? dapp-url bot-url whisper-identity]} :contact
|
||||
:as params}]]
|
||||
(cond
|
||||
(= console-chat-id whisper-identity)
|
||||
(dispatch [::validate-hash whisper-identity js-res/console-js])
|
||||
|
||||
(= wallet-chat-id whisper-identity)
|
||||
(dispatch [::validate-hash whisper-identity js-res/wallet-js])
|
||||
(js-res/local-resource? bot-url)
|
||||
(dispatch [::validate-hash params (js-res/get-resource bot-url)])
|
||||
|
||||
(and dapp? dapp-url)
|
||||
(http-get (s/join "/" [dapp-url commands-js])
|
||||
(http-get (s/join "/" [dapp-url "commands.js"])
|
||||
(fn [response]
|
||||
(and
|
||||
(string? (.text response))
|
||||
|
@ -48,13 +49,14 @@
|
|||
#(dispatch [::validate-hash whisper-identity js-res/dapp-js]))
|
||||
|
||||
:else
|
||||
(dispatch [::validate-hash whisper-identity js-res/commands-js])))
|
||||
(dispatch [::validate-hash params js-res/commands-js])))
|
||||
|
||||
(defn dispatch-loaded!
|
||||
[db [identity file]]
|
||||
[db [{{:keys [whisper-identity]} :contact
|
||||
:as params} file]]
|
||||
(if (::valid-hash db)
|
||||
(dispatch [::parse-commands! identity file])
|
||||
(dispatch [::loading-failed! identity ::wrong-hash])))
|
||||
(dispatch [::parse-commands! params file])
|
||||
(dispatch [::loading-failed! whisper-identity ::wrong-hash])))
|
||||
|
||||
(defn get-hash-by-identity
|
||||
[db identity]
|
||||
|
@ -65,19 +67,23 @@
|
|||
;; todo tbd hashing algorithm
|
||||
(hash file))
|
||||
|
||||
(defn parse-commands! [_ [identity file]]
|
||||
(status/parse-jail identity file
|
||||
(fn [result]
|
||||
(let [{:keys [error result]} (json->clj result)]
|
||||
(log/debug "Error parsing commands: " error result)
|
||||
(if error
|
||||
(dispatch [::loading-failed! identity ::error-in-jail error])
|
||||
(if identity
|
||||
(dispatch [::add-commands identity file result])
|
||||
(dispatch [::add-all-commands result])))))))
|
||||
(defn parse-commands!
|
||||
[_ [{{:keys [whisper-identity]} :contact
|
||||
:keys [callback]}
|
||||
file]]
|
||||
(status/parse-jail
|
||||
whisper-identity file
|
||||
(fn [result]
|
||||
(let [{:keys [error result]} (json->clj result)]
|
||||
(log/debug "Parsing commands results: " error result)
|
||||
(if error
|
||||
(dispatch [::loading-failed! whisper-identity ::error-in-jail error])
|
||||
(do
|
||||
(dispatch [::add-commands whisper-identity file result])
|
||||
(when callback (callback))))))))
|
||||
|
||||
(defn validate-hash
|
||||
[db [identity file]]
|
||||
[db [_ file]]
|
||||
(let [valid? true
|
||||
;; todo check
|
||||
#_(= (get-hash-by-identity db identity)
|
||||
|
@ -102,18 +108,36 @@
|
|||
|
||||
(defn add-commands
|
||||
[db [id _ {:keys [commands responses autorun]}]]
|
||||
(let [account @(subscribe [:get-current-account])
|
||||
commands' (filter-forbidden-names account id commands)
|
||||
responses' (filter-forbidden-names account id responses)]
|
||||
(-> db
|
||||
(assoc-in [id :commands] (mark-as :command commands'))
|
||||
(assoc-in [id :responses] (mark-as :response responses'))
|
||||
(assoc-in [id :commands-loaded] true)
|
||||
(assoc-in [id :autorun] autorun))))
|
||||
(let [account @(subscribe [:get-current-account])
|
||||
commands' (filter-forbidden-names account id commands)
|
||||
global-command (:global commands')
|
||||
commands'' (apply dissoc commands' [:init :global])
|
||||
responses' (filter-forbidden-names account id responses)]
|
||||
(cond-> db
|
||||
|
||||
(get-in db [:chats id])
|
||||
(update-in [:chats id] assoc
|
||||
:commands (mark-as :command commands'')
|
||||
:responses (mark-as :response responses')
|
||||
:commands-loaded true
|
||||
:autorun autorun
|
||||
:global-command global-command)
|
||||
|
||||
global-command
|
||||
(update :global-commands assoc (keyword id)
|
||||
(assoc global-command :bot id
|
||||
:type :command)))))
|
||||
|
||||
(defn save-commands-js!
|
||||
[_ [id file]]
|
||||
(commands/save {:chat-id id :file file}))
|
||||
#_(commands/save {:chat-id id :file file}))
|
||||
|
||||
(defn save-global-command!
|
||||
[{:keys [global-commands]} [id]]
|
||||
(let [command (get global-commands (keyword id))]
|
||||
(when command
|
||||
(contacts/save {:whisper-identity id
|
||||
:global-command command}))))
|
||||
|
||||
(defn loading-failed!
|
||||
[db [id reason details]]
|
||||
|
@ -126,6 +150,13 @@
|
|||
(show-popup "Error" m)
|
||||
(log/debug m))))
|
||||
|
||||
(reg-handler :check-and-load-commands!
|
||||
(u/side-effect!
|
||||
(fn [{:keys [chats]} [identity callback]]
|
||||
(if (get-in chats [identity :commands-loaded])
|
||||
(callback)
|
||||
(dispatch [:load-commands! identity callback])))))
|
||||
|
||||
(reg-handler :load-commands! (u/side-effect! load-commands!))
|
||||
(reg-handler ::fetch-commands! (u/side-effect! fetch-commands!))
|
||||
|
||||
|
@ -136,8 +167,8 @@
|
|||
(reg-handler ::parse-commands! (u/side-effect! parse-commands!))
|
||||
|
||||
(reg-handler ::add-commands
|
||||
[(path :chats)
|
||||
(after save-commands-js!)
|
||||
[(after save-commands-js!)
|
||||
(after save-global-command!)
|
||||
(after #(dispatch [:check-autorun]))
|
||||
(after #(dispatch [:update-suggestions]))
|
||||
(after (fn [_ [id]]
|
||||
|
@ -145,11 +176,6 @@
|
|||
(dispatch [:invoke-chat-loaded-callbacks id])))]
|
||||
add-commands)
|
||||
|
||||
(reg-handler ::add-all-commands
|
||||
(fn [db [{:keys [commands responses]}]]
|
||||
(assoc db :all-commands {:commands (mark-as :command commands)
|
||||
:responses (mark-as :response responses)})))
|
||||
|
||||
(reg-handler ::loading-failed! (u/side-effect! loading-failed!))
|
||||
|
||||
(reg-handler :add-commands-loading-callback
|
||||
|
|
|
@ -103,13 +103,22 @@
|
|||
db)))
|
||||
|
||||
(defn load-contacts! [db _]
|
||||
(let [contacts (->> (contacts/get-all)
|
||||
(map (fn [{:keys [whisper-identity] :as contact}]
|
||||
[whisper-identity contact]))
|
||||
(into {}))]
|
||||
(let [contacts-list (->> (contacts/get-all)
|
||||
(map (fn [{:keys [whisper-identity] :as contact}]
|
||||
[whisper-identity contact])))
|
||||
global-commands (->> contacts-list
|
||||
(filter (fn [[_ c]] (:global-command c)))
|
||||
(map (fn [[id {:keys [global-command]}]]
|
||||
[(keyword id) (-> global-command
|
||||
(update :params vals)
|
||||
(assoc :bot id
|
||||
:type :command))]))
|
||||
(into {}))
|
||||
contacts (into {} contacts-list)]
|
||||
(doseq [[_ contact] contacts]
|
||||
(dispatch [:watch-contact contact]))
|
||||
(assoc db :contacts contacts)))
|
||||
(assoc db :contacts contacts
|
||||
:global-commands global-commands)))
|
||||
|
||||
(register-handler :load-contacts load-contacts!)
|
||||
|
||||
|
@ -216,34 +225,39 @@
|
|||
(u/side-effect!
|
||||
(fn [{:keys [chats groups]}]
|
||||
(let [default-contacts js-res/default-contacts
|
||||
default-groups js-res/default-contact-groups]
|
||||
default-groups js-res/default-contact-groups]
|
||||
(dispatch [:add-groups (mapv
|
||||
(fn [[id {:keys [name contacts]}]]
|
||||
{:group-id (clojure.core/name id)
|
||||
{:group-id (clojure.core/name id)
|
||||
:name (:en name)
|
||||
:order 0
|
||||
:timestamp (random/timestamp)
|
||||
:contacts (mapv #(hash-map :identity %) contacts)})
|
||||
default-groups)])
|
||||
(doseq [[id {:keys [name photo-path public-key add-chat?
|
||||
dapp? dapp-url dapp-hash]}] default-contacts]
|
||||
(doseq [[id {:keys [name photo-path public-key add-chat? has-global-command?
|
||||
dapp? dapp-url dapp-hash bot-url]}] default-contacts]
|
||||
(let [id' (clojure.core/name id)]
|
||||
(when-not (chats id')
|
||||
(when add-chat?
|
||||
(dispatch [:add-chat id' {:name (:en name)}]))
|
||||
(dispatch [:add-contacts [{:whisper-identity id'
|
||||
:address (public-key->address id')
|
||||
:name (:en name)
|
||||
:photo-path photo-path
|
||||
:public-key public-key
|
||||
:dapp? dapp?
|
||||
:dapp-url (:en dapp-url)
|
||||
:dapp-hash dapp-hash}]]))))))))
|
||||
(dispatch [:add-contacts [{:whisper-identity id'
|
||||
:address (public-key->address id')
|
||||
:name (:en name)
|
||||
:photo-path photo-path
|
||||
:public-key public-key
|
||||
:dapp? dapp?
|
||||
:dapp-url (:en dapp-url)
|
||||
:bot-url bot-url
|
||||
:has-global-command? has-global-command?
|
||||
:dapp-hash dapp-hash}]])
|
||||
(when bot-url
|
||||
(dispatch [:load-commands! id'])))))))))
|
||||
|
||||
|
||||
(register-handler :add-contacts
|
||||
(-> add-new-contacts
|
||||
((after save-contacts!))
|
||||
((after add-contacts-to-groups))))
|
||||
[(after save-contacts!)
|
||||
(after add-contacts-to-groups)]
|
||||
add-new-contacts)
|
||||
|
||||
(defn add-new-contact [db [_ {:keys [whisper-identity] :as contact}]]
|
||||
(-> db
|
||||
|
@ -270,9 +284,9 @@
|
|||
(register-handler :add-pending-contact
|
||||
(u/side-effect!
|
||||
(fn [{:keys [chats contacts]} [_ chat-id]]
|
||||
(let [contact (if-let [contact-info (get-in chats [chat-id :contact-info])]
|
||||
(read-string contact-info)
|
||||
(assoc (get contacts chat-id) :pending? false))
|
||||
(let [contact (if-let [contact-info (get-in chats [chat-id :contact-info])]
|
||||
(read-string contact-info)
|
||||
(assoc (get contacts chat-id) :pending? false))
|
||||
contact' (assoc contact :address (public-key->address chat-id))]
|
||||
(dispatch [::prepare-contact contact'])
|
||||
(dispatch [:watch-contact contact'])
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
[status-im.data-store.realm.schemas.account.v2.core :as v2]
|
||||
[status-im.data-store.realm.schemas.account.v3.core :as v3]
|
||||
[status-im.data-store.realm.schemas.account.v4.core :as v4]
|
||||
[status-im.data-store.realm.schemas.account.v5.core :as v5]))
|
||||
|
||||
[status-im.data-store.realm.schemas.account.v5.core :as v5]
|
||||
[status-im.data-store.realm.schemas.account.v6.core :as v6]))
|
||||
|
||||
; put schemas ordered by version
|
||||
(def schemas [{:schema v1/schema
|
||||
|
@ -21,4 +21,7 @@
|
|||
:migration v4/migration}
|
||||
{:schema v5/schema
|
||||
:schemaVersion 5
|
||||
:migration v5/migration}])
|
||||
:migration v5/migration}
|
||||
{:schema v6/schema
|
||||
:schemaVersion 6
|
||||
:migration v6/migration}])
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v6.command
|
||||
(:require [taoensso.timbre :as log]))
|
||||
|
||||
(def schema {:name :command
|
||||
:properties {:description {:type :string
|
||||
:optional true}
|
||||
:color {:type :string
|
||||
:optional true}
|
||||
:name {:type :string}
|
||||
:params {:type :list
|
||||
:objectType :command-parameter}
|
||||
:title {:type :string
|
||||
:optional true}
|
||||
:has-handler {:type :bool
|
||||
:default true}
|
||||
:fullscreen {:type :bool
|
||||
:default true}
|
||||
:suggestions-trigger {:type :string
|
||||
:default "on-change"}}})
|
||||
|
||||
(defn migration [_ _]
|
||||
(log/debug "migrating chat-contact schema"))
|
|
@ -0,0 +1,9 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v6.command-parameter
|
||||
(:require [taoensso.timbre :as log]))
|
||||
|
||||
(def schema {:name :command-parameter
|
||||
:properties {:name {:type :string}
|
||||
:type {:type :string}}})
|
||||
|
||||
(defn migration [_ _]
|
||||
(log/debug "migrating command-parameter schema"))
|
|
@ -0,0 +1,32 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v6.contact
|
||||
(:require [taoensso.timbre :as log]))
|
||||
|
||||
(def schema {:name :contact
|
||||
:primaryKey :whisper-identity
|
||||
:properties {:address {:type :string :optional true}
|
||||
:whisper-identity :string
|
||||
:name {:type :string :optional true}
|
||||
:photo-path {:type :string :optional true}
|
||||
:last-updated {:type :int :default 0}
|
||||
:last-online {:type :int :default 0}
|
||||
:pending? {:type :bool :default false}
|
||||
:status {:type :string :optional true}
|
||||
:public-key {:type :string
|
||||
:optional true}
|
||||
:private-key {:type :string
|
||||
:optional true}
|
||||
:dapp? {:type :bool
|
||||
:default false}
|
||||
:dapp-url {:type :string
|
||||
:optional true}
|
||||
:bot-url {:type :string
|
||||
:optional true}
|
||||
:global-command {:type :command
|
||||
:optional true}
|
||||
:dapp-hash {:type :int
|
||||
:optional true}
|
||||
:debug? {:type :bool
|
||||
:default false}}})
|
||||
|
||||
(defn migration [old-realm new-realm]
|
||||
(log/debug "migrating contact schema v6"))
|
|
@ -0,0 +1,38 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v6.core
|
||||
(:require [status-im.data-store.realm.schemas.account.v4.chat :as chat]
|
||||
[status-im.data-store.realm.schemas.account.v1.chat-contact :as chat-contact]
|
||||
[status-im.data-store.realm.schemas.account.v6.command :as command]
|
||||
[status-im.data-store.realm.schemas.account.v6.command-parameter :as command-parameter]
|
||||
[status-im.data-store.realm.schemas.account.v6.contact :as contact]
|
||||
[status-im.data-store.realm.schemas.account.v1.discover :as discover]
|
||||
[status-im.data-store.realm.schemas.account.v1.kv-store :as kv-store]
|
||||
[status-im.data-store.realm.schemas.account.v4.message :as message]
|
||||
[status-im.data-store.realm.schemas.account.v1.pending-message :as pending-message]
|
||||
[status-im.data-store.realm.schemas.account.v1.processed-message :as processed-message]
|
||||
[status-im.data-store.realm.schemas.account.v1.request :as request]
|
||||
[status-im.data-store.realm.schemas.account.v1.tag :as tag]
|
||||
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
|
||||
[status-im.data-store.realm.schemas.account.v5.contact-group :as contact-group]
|
||||
[status-im.data-store.realm.schemas.account.v5.group-contact :as group-contact]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def schema [chat/schema
|
||||
chat-contact/schema
|
||||
command/schema
|
||||
command-parameter/schema
|
||||
contact/schema
|
||||
discover/schema
|
||||
kv-store/schema
|
||||
message/schema
|
||||
pending-message/schema
|
||||
processed-message/schema
|
||||
request/schema
|
||||
tag/schema
|
||||
user-status/schema
|
||||
contact-group/schema
|
||||
group-contact/schema])
|
||||
|
||||
(defn migration [old-realm new-realm]
|
||||
(log/debug "migrating v5 account database: " old-realm new-realm)
|
||||
(chat/migration old-realm new-realm)
|
||||
(contact/migration old-realm new-realm))
|
|
@ -44,13 +44,14 @@
|
|||
|
||||
(register-handler :initialize-db
|
||||
(fn [{:keys [status-module-initialized? status-node-started?
|
||||
network-status network]} _]
|
||||
network-status network first-run]} _]
|
||||
(data-store/init)
|
||||
(assoc app-db :current-account-id nil
|
||||
:network-status network-status
|
||||
:status-module-initialized? (or p/ios? js/goog.DEBUG status-module-initialized?)
|
||||
:status-node-started? status-node-started?
|
||||
:network (or network :testnet))))
|
||||
:network (or network :testnet)
|
||||
:first-run (or (nil? first-run) first-run))))
|
||||
|
||||
(register-handler :initialize-account-db
|
||||
(fn [db _]
|
||||
|
@ -81,12 +82,22 @@
|
|||
|
||||
(register-handler :reset-app
|
||||
(u/side-effect!
|
||||
(fn [_ _]
|
||||
(fn [{:keys [first-run] :as db} [_ callback]]
|
||||
(dispatch [:initialize-db])
|
||||
(dispatch [:load-accounts])
|
||||
(dispatch [:init-console-chat])
|
||||
(dispatch [:load-default-contacts!])
|
||||
(dispatch [:load-commands!]))))
|
||||
|
||||
(dispatch [::init-chats! callback]))))
|
||||
|
||||
(register-handler ::init-chats!
|
||||
(u/side-effect!
|
||||
(fn [{:keys [first-run accounts] :as db} [_ callback]]
|
||||
(when first-run
|
||||
(dispatch [:set :first-run false]))
|
||||
(when (or (not first-run) (empty? accounts))
|
||||
(dispatch [:init-console-chat])
|
||||
(dispatch [:load-default-contacts!])
|
||||
(dispatch [:load-commands!])
|
||||
(when callback (callback))))))
|
||||
|
||||
(def ecc (js/require "eccjs"))
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
[(str/blank? username)
|
||||
(h/matches username console-chat-id)
|
||||
(h/matches username wallet-chat-id)
|
||||
(str/includes? username chat-consts/command-char)])))
|
||||
(str/includes? username chat-consts/command-char)
|
||||
(str/includes? username chat-consts/bot-char)])))
|
||||
|
||||
(defn correct-email? [email]
|
||||
(let [pattern #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"]
|
||||
|
|
|
@ -1,14 +1,39 @@
|
|||
(ns status-im.utils.js-resources
|
||||
(:require-macros [status-im.utils.slurp :refer [slurp]])
|
||||
(:require [status-im.utils.types :refer [json->clj]]))
|
||||
(:require-macros [status-im.utils.slurp :refer [slurp slurp-bot]])
|
||||
(:require [status-im.utils.types :refer [json->clj]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(def local-protocol "local://")
|
||||
|
||||
(defn local-resource? [url]
|
||||
(and (string? url) (s/starts-with? url local-protocol)))
|
||||
|
||||
(def default-contacts (json->clj (slurp "resources/default_contacts.json")))
|
||||
(def default-contact-groups (json->clj (slurp "resources/default_contact_groups.json")))
|
||||
|
||||
(def commands-js (slurp "resources/commands.js"))
|
||||
(def console-js (slurp "resources/console.js"))
|
||||
(def status-js (slurp "resources/status.js"))
|
||||
(def wallet-js (slurp "resources/wallet.js"))
|
||||
(def wallet-js (slurp-bot :wallet))
|
||||
|
||||
(def console-js (slurp-bot :console "web3_metadata.js"))
|
||||
|
||||
(def browse-js (slurp-bot :browse))
|
||||
|
||||
(def mailman-js (slurp-bot :mailman ))
|
||||
|
||||
(def commands-js wallet-js)
|
||||
|
||||
(def resources
|
||||
{:wallet-bot wallet-js
|
||||
:console-bot console-js
|
||||
:browse-bot browse-js
|
||||
:mailman-bot mailman-js})
|
||||
|
||||
(defn get-resource [url]
|
||||
(let [resource-name (keyword (subs url (count local-protocol)))]
|
||||
(resources resource-name)))
|
||||
|
||||
(def status-js (str (slurp "resources/status.js")
|
||||
(slurp "resources/i18n.js")))
|
||||
|
||||
(def dapp-js (str (slurp "resources/dapp.js")))
|
||||
|
||||
(def webview-js (slurp "resources/webview.js"))
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
(ns status-im.utils.slurp
|
||||
(:refer-clojure :exclude [slurp]))
|
||||
(:refer-clojure :exclude [slurp])
|
||||
(:require [clojure.string :as s]))
|
||||
|
||||
(defmacro slurp [file]
|
||||
(clojure.core/slurp file))
|
||||
|
||||
(defmacro slurp-bot [bot-name & files]
|
||||
(->> (concat files ["translations.js" "bot.js"])
|
||||
(map #(clojure.core/slurp (s/join "/" ["bots" (name bot-name) %])))
|
||||
(apply str)))
|
||||
|
|
Loading…
Reference in New Issue