mirror of
https://github.com/status-im/status-react.git
synced 2025-02-22 07:38:34 +00:00
Password and phone inputs [chat-ui]
This commit is contained in:
parent
35210f043d
commit
6e4931417b
2
env/dev/env/android/main.cljs
vendored
2
env/dev/env/android/main.cljs
vendored
@ -19,6 +19,6 @@
|
||||
:heads-up-display false
|
||||
:jsload-callback callback)
|
||||
|
||||
(rr/enable-re-frisk-remote!)
|
||||
(rr/enable-re-frisk-remote! {:host "10.0.2.2:4567"})
|
||||
|
||||
(core/init)
|
||||
|
2
env/dev/env/ios/main.cljs
vendored
2
env/dev/env/ios/main.cljs
vendored
@ -16,6 +16,6 @@
|
||||
:heads-up-display false
|
||||
:jsload-callback #(swap! cnt inc))
|
||||
|
||||
(rr/enable-re-frisk-remote!)
|
||||
(rr/enable-re-frisk-remote! {:host "localhost:4567"})
|
||||
|
||||
(core/init)
|
@ -1,9 +1,11 @@
|
||||
var TopLevel = {
|
||||
"abs" : function () {},
|
||||
"ActionSheetIOS" : function () {},
|
||||
"addEntropy" : function () {},
|
||||
"addEventListener" : function () {},
|
||||
"addListener" : function () {},
|
||||
"addOrientationListener" : function () {},
|
||||
"addSymKey" : function () {},
|
||||
"Alert" : function () {},
|
||||
"alert" : function () {},
|
||||
"Animated" : function () {},
|
||||
@ -81,13 +83,13 @@ var TopLevel = {
|
||||
"goog" : function () {},
|
||||
"guid" : function () {},
|
||||
"hash" : function () {},
|
||||
"hasSymKey" : function () {},
|
||||
"headers" : function () {},
|
||||
"height" : function () {},
|
||||
"hex" : function () {},
|
||||
"hide" : function () {},
|
||||
"HttpProvider" : function () {},
|
||||
"IBGLog" : function () {},
|
||||
"indexOf" : function () {},
|
||||
"initialPage" : function () {},
|
||||
"initJail" : function () {},
|
||||
"isAddress" : function () {},
|
||||
@ -196,6 +198,7 @@ var TopLevel = {
|
||||
"toAscii" : function () {},
|
||||
"toBits" : function () {},
|
||||
"toDecimal" : function () {},
|
||||
"toHex" : function () {},
|
||||
"toLocaleString" : function () {},
|
||||
"toLowerCase" : function () {},
|
||||
"toNumber" : function () {},
|
||||
|
@ -10,7 +10,7 @@ I18n.translations = {
|
||||
|
||||
password_description: 'Password',
|
||||
password_placeholder: 'Type your password',
|
||||
password_placeholder2: 'Please re-enter password to confirm',
|
||||
password_placeholder2: 'Confirm',
|
||||
password_error: 'Password should be not less then 6 symbols.',
|
||||
password_error1: 'Password confirmation doesn\'t match password.',
|
||||
password_validation_title: 'Password',
|
||||
@ -1653,6 +1653,7 @@ var phoneConfig = {
|
||||
color: "#5bb2a2",
|
||||
title: I18n.t('phone_title'),
|
||||
description: I18n.t('phone_description'),
|
||||
sequentialParams: true,
|
||||
validator: function (params) {
|
||||
return {
|
||||
validationHandler: "phone",
|
||||
@ -1872,32 +1873,40 @@ status.response({
|
||||
color: "#7099e6",
|
||||
description: I18n.t('password_description'),
|
||||
icon: "lock_white",
|
||||
params: [{
|
||||
name: "password",
|
||||
type: status.types.PASSWORD,
|
||||
placeholder: I18n.t('password_placeholder'),
|
||||
hidden: true
|
||||
}, {
|
||||
name: "password_confirmation",
|
||||
type: status.types.PASSWORD,
|
||||
placeholder: "Confirm",
|
||||
hidden: true
|
||||
}],
|
||||
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["password_confirmation"] != params["password"]) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('password_validation_title'),
|
||||
I18n.t('password_error1')
|
||||
);
|
||||
return {markup: error};
|
||||
}
|
||||
if (params.password.length < 6) {
|
||||
var error = status.components.validationMessage(
|
||||
I18n.t('password_validation_title'),
|
||||
I18n.t('password_error')
|
||||
);
|
||||
return {markup: error};
|
||||
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 = {
|
||||
|
@ -36,6 +36,7 @@ Command.prototype.create = function (com) {
|
||||
this["on-send"] = com.onSend;
|
||||
this.fullscreen = com.fullscreen;
|
||||
this.request = com.request;
|
||||
this["sequential-params"] = com.sequentialParams;
|
||||
this.addToCatalog();
|
||||
|
||||
return this;
|
||||
|
@ -3,7 +3,6 @@
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.password-input :as password-input]
|
||||
[status-im.chat.models.suggestions :as suggestions]
|
||||
[status-im.components.react :as react-comp]
|
||||
[status-im.components.status :as status]
|
||||
@ -16,27 +15,17 @@
|
||||
(handlers/register-handler
|
||||
:set-chat-input-text
|
||||
(fn [{:keys [current-chat-id chats chat-ui-props] :as db} [_ text chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
selection (get-in chat-ui-props [chat-id :selection])]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
ends-with-space? (input-model/text-ends-with-space? text)]
|
||||
(dispatch [:update-suggestions chat-id text])
|
||||
|
||||
(if-let [{command :command} (input-model/selected-chat-command db chat-id text)]
|
||||
(let [{old-args :args} (input-model/selected-chat-command db chat-id)
|
||||
text-splitted (input-model/split-command-args text)
|
||||
new-args (rest text-splitted)
|
||||
modifiers (input-model/add-modifiers (:params command) new-args)
|
||||
addition (if (input-model/text-ends-with-space? text)
|
||||
const/spacing-char)
|
||||
new-params {:modified-text (str (input-model/apply-modifiers text-splitted modifiers)
|
||||
addition)
|
||||
:input-text (str (input-model/make-input-text modifiers
|
||||
text-splitted
|
||||
old-args
|
||||
selection)
|
||||
addition)}]
|
||||
(update-in db [:chats chat-id] merge new-params))
|
||||
(update-in db [:chats chat-id] merge {:input-text text
|
||||
:modified-text nil})))))
|
||||
text-splitted (input-model/split-command-args text)
|
||||
new-args (rest text-splitted)
|
||||
new-input-text (input-model/make-input-text text-splitted old-args)]
|
||||
(assoc-in db [:chats chat-id :input-text] new-input-text))
|
||||
(assoc-in db [:chats chat-id :input-text] text)))))
|
||||
|
||||
(handlers/register-handler
|
||||
:add-to-chat-input-text
|
||||
@ -58,7 +47,11 @@
|
||||
(dispatch [:set-chat-ui-props :result-box nil])
|
||||
(dispatch [:set-chat-ui-props :validation-messages nil])
|
||||
(dispatch [:load-chat-parameter-box command 0])
|
||||
(dispatch [:chat-input-focus]))))
|
||||
(if (:sequential-params command)
|
||||
(js/setTimeout
|
||||
#(dispatch [:chat-input-focus :seq-input-ref])
|
||||
100)
|
||||
(dispatch [:chat-input-focus :input-ref])))))
|
||||
|
||||
(handlers/register-handler
|
||||
:set-chat-input-metadata
|
||||
@ -72,22 +65,29 @@
|
||||
(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))
|
||||
command-name (first command)
|
||||
command-args (into [] (rest command))
|
||||
command-args (if (< index (count command-args))
|
||||
(assoc command-args index arg)
|
||||
(conj command-args arg))]
|
||||
(dispatch [:set-chat-input-text (str command-name
|
||||
const/spacing-char
|
||||
(input-model/join-command-args command-args)
|
||||
const/spacing-char)])))))
|
||||
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)
|
||||
command-args (into [] (rest command))
|
||||
command-args (if (< index (count command-args))
|
||||
(assoc command-args index arg)
|
||||
(conj command-args arg))]
|
||||
(dispatch [:set-chat-input-text (str command-name
|
||||
const/spacing-char
|
||||
(input-model/join-command-args command-args)
|
||||
const/spacing-char)])))))))
|
||||
|
||||
(handlers/register-handler
|
||||
:chat-input-focus
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id chat-ui-props] :as db}]
|
||||
(when-let [ref (get-in chat-ui-props [current-chat-id :input-ref])]
|
||||
(.focus ref)))))
|
||||
(fn [{:keys [current-chat-id chat-ui-props] :as db} [_ ref]]
|
||||
(try
|
||||
(when-let [ref (get-in chat-ui-props [current-chat-id ref])]
|
||||
(.focus ref))
|
||||
(catch :default e
|
||||
(log/debug "Cannot focus the reference"))))))
|
||||
|
||||
(handlers/register-handler
|
||||
:update-suggestions
|
||||
@ -152,34 +152,35 @@
|
||||
::proceed-command
|
||||
(handlers/side-effect!
|
||||
(fn [db [_ 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])}]))))
|
||||
(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])}])))))
|
||||
|
||||
(handlers/register-handler
|
||||
::proceed-validation-messages
|
||||
(handlers/side-effect!
|
||||
(fn [db [_ command chat-id {:keys [markup validationHandler parameters] :as errors}]]
|
||||
(fn [db [_ command chat-id {:keys [markup validationHandler parameters] :as errors} proceed-fn]]
|
||||
(let [set-errors #(do (dispatch [:set-chat-ui-props :validation-messages %])
|
||||
(dispatch [:set-chat-ui-props :sending-in-progress? false]))
|
||||
proceed #(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 [:set-chat-ui-props :sending-in-progress? false]))]
|
||||
(cond
|
||||
markup
|
||||
(set-errors markup)
|
||||
|
||||
validationHandler
|
||||
(do (dispatch [::execute-validation-handler validationHandler parameters set-errors proceed])
|
||||
(do (dispatch [::execute-validation-handler validationHandler parameters set-errors proceed-fn])
|
||||
(dispatch [:set-chat-ui-props :sending-in-progress? false]))
|
||||
|
||||
:default
|
||||
(proceed))))))
|
||||
(proceed-fn))))))
|
||||
|
||||
(handlers/register-handler
|
||||
::execute-validation-handler
|
||||
@ -236,11 +237,19 @@
|
||||
:send-current-message
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id] :as db} [_ chat-id]]
|
||||
(dispatch [:set-chat-ui-props :sending-in-progress? true])
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
chat-command (input-model/selected-chat-command db chat-id)]
|
||||
(if chat-command
|
||||
chat-command (input-model/selected-chat-command db chat-id)
|
||||
seq-command? (get-in chat-command [:command :sequential-params])
|
||||
chat-command (if seq-command?
|
||||
(let [args (get-in db [:chats chat-id :seq-arguments])]
|
||||
(assoc chat-command :args args))
|
||||
(update chat-command :args #(remove str/blank? %)))]
|
||||
(if (:command chat-command)
|
||||
(if (= :complete (input-model/command-completion chat-command))
|
||||
(dispatch [::proceed-command chat-command chat-id])
|
||||
(do
|
||||
(dispatch [::proceed-command chat-command chat-id])
|
||||
(dispatch [:clear-seq-arguments chat-id]))
|
||||
(let [text (get-in db [:chats chat-id :input-text])]
|
||||
(dispatch [:set-chat-ui-props :sending-in-progress? false])
|
||||
(when-not (input-model/text-ends-with-space? text)
|
||||
@ -261,4 +270,48 @@
|
||||
params
|
||||
(fn [{:keys [result] :as data}]
|
||||
(dispatch [:suggestions-handler {:chat-id chat-id
|
||||
:result data}])))))))
|
||||
:result data}])))))))
|
||||
|
||||
(handlers/register-handler
|
||||
:clear-seq-arguments
|
||||
(fn [{:keys [current-chat-id chats] :as db} [_ chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)]
|
||||
(-> db
|
||||
(assoc-in [:chats chat-id :seq-arguments] [])
|
||||
(assoc-in [:chats chat-id :seq-argument-input-text] nil)))))
|
||||
|
||||
(handlers/register-handler
|
||||
:update-seq-arguments
|
||||
(fn [{:keys [current-chat-id chats] :as db} [_ chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
text (get-in chats [chat-id :seq-argument-input-text])]
|
||||
(-> db
|
||||
(update-in [:chats chat-id :seq-arguments] #(into [] (conj % text)))
|
||||
(assoc-in [:chats chat-id :seq-argument-input-text] nil)))))
|
||||
|
||||
(handlers/register-handler
|
||||
:send-seq-argument
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id chats] :as db} [_ chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
text (get-in chats [chat-id :seq-argument-input-text])
|
||||
seq-arguments (get-in db [:chats chat-id :seq-arguments])
|
||||
command (-> (input-model/selected-chat-command db chat-id)
|
||||
(assoc :args (into [] (conj seq-arguments text))))
|
||||
args (get-in chats [chat-id :seq-arguments])
|
||||
after-validation #(do
|
||||
(dispatch [:update-seq-arguments chat-id])
|
||||
(dispatch [:send-current-message]))]
|
||||
(dispatch [::request-command-data
|
||||
{:command command
|
||||
:chat-id chat-id
|
||||
:data-type :validator
|
||||
:after #(do
|
||||
(dispatch [::proceed-validation-messages
|
||||
command chat-id %2 after-validation]))}])))))
|
||||
|
||||
(handlers/register-handler
|
||||
:set-chat-seq-arg-input-text
|
||||
(fn [{:keys [current-chat-id] :as db} [_ text chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)]
|
||||
(assoc-in db [:chats chat-id :seq-argument-input-text] text))))
|
@ -2,15 +2,15 @@
|
||||
(:require [clojure.string :as str]
|
||||
[status-im.components.react :as rc]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.chat.models.password-input :as password-input]
|
||||
[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]))
|
||||
|
||||
(defn text-ends-with-space? [text]
|
||||
(= (str/last-index-of text const/spacing-char)
|
||||
(dec (count text))))
|
||||
(when text
|
||||
(= (str/last-index-of text const/spacing-char)
|
||||
(dec (count text)))))
|
||||
|
||||
(defn possible-chat-actions [db chat-id]
|
||||
(let [{:keys [commands requests]} (get-in db [:chats chat-id])
|
||||
@ -25,22 +25,27 @@
|
||||
(into commands responses)))
|
||||
|
||||
(defn split-command-args [command-text]
|
||||
(let [splitted (str/split command-text const/spacing-char)]
|
||||
(first
|
||||
(reduce (fn [[list command-started?] arg]
|
||||
(let [quotes-count (count (filter #(= % const/arg-wrapping-char) arg))
|
||||
has-quote? (and (= quotes-count 1)
|
||||
(str/index-of arg const/arg-wrapping-char))
|
||||
arg (str/replace arg #"\"" "")
|
||||
new-list (if command-started?
|
||||
(let [index (dec (count list))]
|
||||
(update list index str const/spacing-char arg))
|
||||
(conj list arg))
|
||||
command-continues? (or (and command-started? (not has-quote?))
|
||||
(and (not command-started?) has-quote?))]
|
||||
[new-list command-continues?]))
|
||||
[[] false]
|
||||
splitted))))
|
||||
(let [space? (text-ends-with-space? command-text)
|
||||
command-text (if space?
|
||||
(str command-text ".")
|
||||
command-text)
|
||||
splitted (cond-> (str/split command-text const/spacing-char)
|
||||
space? (drop-last))]
|
||||
(->> splitted
|
||||
(reduce (fn [[list command-started?] arg]
|
||||
(let [quotes-count (count (filter #(= % const/arg-wrapping-char) arg))
|
||||
has-quote? (and (= quotes-count 1)
|
||||
(str/index-of arg const/arg-wrapping-char))
|
||||
arg (str/replace arg #"\"" "")
|
||||
new-list (if command-started?
|
||||
(let [index (dec (count list))]
|
||||
(update list index str const/spacing-char arg))
|
||||
(conj list arg))
|
||||
command-continues? (or (and command-started? (not has-quote?))
|
||||
(and (not command-started?) has-quote?))]
|
||||
[new-list command-continues?]))
|
||||
[[] false])
|
||||
(first))))
|
||||
|
||||
(defn join-command-args [args]
|
||||
(->> args
|
||||
@ -54,6 +59,7 @@
|
||||
([{:keys [current-chat-id] :as db} chat-id input-text]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
input-metadata (get-in db [:chats chat-id :input-metadata])
|
||||
seq-arguments (get-in db [:chats chat-id :seq-arguments])
|
||||
possible-actions (possible-chat-actions db chat-id)
|
||||
command-args (split-command-args input-text)
|
||||
command-name (first command-args)]
|
||||
@ -66,24 +72,33 @@
|
||||
:metadata (if (not= :any to-message-id)
|
||||
(assoc input-metadata :to-message-id to-message-id)
|
||||
input-metadata)
|
||||
:args (remove empty? (rest command-args))}))))
|
||||
:args (if (empty? seq-arguments)
|
||||
(rest command-args)
|
||||
seq-arguments)}))))
|
||||
([{:keys [current-chat-id] :as db} chat-id]
|
||||
(selected-chat-command db chat-id (get-in db [:chats chat-id :input-text]))))
|
||||
|
||||
(defn current-chat-argument-position
|
||||
[{:keys [args] :as command} input-text]
|
||||
[{:keys [args] :as command} input-text seq-arguments]
|
||||
(if command
|
||||
(let [current (count args)]
|
||||
(if (= (last input-text) const/spacing-char)
|
||||
current
|
||||
(dec current)))
|
||||
(let [args-count (count args)]
|
||||
(cond
|
||||
(:sequential-params command)
|
||||
(count seq-arguments)
|
||||
|
||||
(= (last input-text) const/spacing-char)
|
||||
args-count
|
||||
|
||||
:default
|
||||
(dec args-count)))
|
||||
-1))
|
||||
|
||||
(defn argument-position [{:keys [current-chat-id] :as db} chat-id]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
input-text (get-in db [:chats chat-id :input-text])
|
||||
seq-arguments (get-in db [:chats chat-id :seq-arguments])
|
||||
chat-command (selected-chat-command db chat-id)]
|
||||
(current-chat-argument-position chat-command input-text)))
|
||||
(current-chat-argument-position chat-command input-text seq-arguments)))
|
||||
|
||||
(defn command-completion
|
||||
([{:keys [current-chat-id] :as db} chat-id]
|
||||
@ -92,7 +107,8 @@
|
||||
chat-command (selected-chat-command db chat-id)]
|
||||
(command-completion chat-command)))
|
||||
([{:keys [args] :as chat-command}]
|
||||
(let [params (get-in chat-command [:command :params])
|
||||
(let [args (remove str/blank? args)
|
||||
params (get-in chat-command [:command :params])
|
||||
required-params (remove :optional params)]
|
||||
(if chat-command
|
||||
(cond
|
||||
@ -134,30 +150,6 @@
|
||||
{:title (i18n/label :t/phone-number)
|
||||
:description (i18n/label :t/invalid-phone)}]))))
|
||||
|
||||
(def text-modifiers
|
||||
[password-input/modifier])
|
||||
|
||||
(defn add-modifiers [params new-args]
|
||||
(->> new-args
|
||||
(map-indexed (fn [i arg]
|
||||
{:position i
|
||||
:value arg
|
||||
:modifier (-> (filter
|
||||
(fn [mod]
|
||||
((:execute-when mod) (get params i)))
|
||||
text-modifiers)
|
||||
(first))}))
|
||||
(into [])))
|
||||
|
||||
(defn apply-modifiers [text-splitted args]
|
||||
(if-let [{:keys [position modifier]} (first args)]
|
||||
(if modifier
|
||||
(let [{:keys [get-modified-text]} modifier
|
||||
modified-text (get-modified-text text-splitted position)]
|
||||
(apply-modifiers modified-text (rest args)))
|
||||
(apply-modifiers text-splitted (rest args)))
|
||||
(str/join const/spacing-char text-splitted)))
|
||||
|
||||
(defn- changed-arg-position [xs ys]
|
||||
(let [longest (into [] (max-key count xs ys))
|
||||
shortest (into [] (if (= longest xs) ys xs))]
|
||||
@ -170,19 +162,15 @@
|
||||
(remove nil?)
|
||||
(first))))
|
||||
|
||||
(defn make-input-text [modifiers [command & args] old-args selection]
|
||||
(let [arg-pos (changed-arg-position args old-args)
|
||||
modifier (get-in modifiers [arg-pos :modifier])
|
||||
new-arg (if (and arg-pos modifier)
|
||||
(let [{:keys [make-change]} modifier]
|
||||
(make-change {:command-name (subs command 1)
|
||||
:old-args old-args
|
||||
:new-args args
|
||||
:arg-pos arg-pos
|
||||
:selection selection}))
|
||||
(get (into [] args) arg-pos))
|
||||
(defn make-input-text [[command & args] old-args]
|
||||
(let [args (into [] args)
|
||||
old-args (into [] old-args)
|
||||
|
||||
arg-pos (changed-arg-position args old-args)
|
||||
new-arg (get args arg-pos)
|
||||
new-args (if arg-pos
|
||||
(assoc (into [] old-args) arg-pos (when new-arg (str/trim new-arg)))
|
||||
(assoc old-args arg-pos (when new-arg
|
||||
(str/trim new-arg)))
|
||||
old-args)]
|
||||
(str
|
||||
command
|
||||
|
@ -1,48 +0,0 @@
|
||||
(ns status-im.chat.models.password-input
|
||||
(:require [status-im.chat.constants :as const]
|
||||
[clojure.string :as str]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- get-modified-text [text arg-pos]
|
||||
(let [hide-fn #(apply str (repeat (count %) const/masking-char))
|
||||
updated-text (update text (inc arg-pos) hide-fn)]
|
||||
updated-text))
|
||||
|
||||
(defn- get-change [{:keys [command-name old-args new-args arg-pos selection]}]
|
||||
(let [old-args (into [] old-args)
|
||||
new-args (into [] new-args)
|
||||
modification (- (count (get new-args arg-pos))
|
||||
(count (get old-args arg-pos)))
|
||||
type (if (> modification 0) :added :removed)
|
||||
position (-> (:start selection)
|
||||
(- (inc (count command-name)))
|
||||
(- (count (str/join const/spacing-char (take arg-pos old-args))))
|
||||
(- modification)
|
||||
(- (if (= arg-pos 0) 0 1)))
|
||||
position (if (= :added type) position (inc position))
|
||||
symbols-count (.abs js/Math modification)]
|
||||
{:type type
|
||||
:position position
|
||||
:symbols (when (= :added type)
|
||||
(subs (get new-args arg-pos)
|
||||
position
|
||||
(+ position symbols-count)))}))
|
||||
|
||||
(defn- make-change [{:keys [command-name old-args new-args arg-pos selection] :as args}]
|
||||
(let [{:keys [type position symbols] :as c} (get-change args)
|
||||
make-change #(if (= type :added)
|
||||
(str (if % (subs % 0 position) "")
|
||||
symbols
|
||||
(if % (subs % position) ""))
|
||||
(str (if % (subs % 0 position) "")
|
||||
(if % (subs % (+ 1 position (count symbols))) "")))
|
||||
args (if (= (count old-args) 0)
|
||||
[const/spacing-char]
|
||||
(into [] old-args))
|
||||
updated-args (update args arg-pos make-change)]
|
||||
(make-change (get args arg-pos))))
|
||||
|
||||
(def modifier
|
||||
{:execute-when :hidden
|
||||
:make-change make-change
|
||||
:get-modified-text get-modified-text})
|
@ -70,10 +70,22 @@
|
||||
:text-align-vertical :center
|
||||
:height min-input-height
|
||||
:align-items :center
|
||||
:android {:left (+ 18 left)
|
||||
:android {:left (+ 15 left)
|
||||
:top -1}
|
||||
:ios {:line-height min-input-height
|
||||
:left (+ 15 left)}})
|
||||
:left (+ 9 left)}})
|
||||
|
||||
(defnstyle input-password-text [left]
|
||||
{:min-width 200
|
||||
:font-size 14
|
||||
:position :absolute
|
||||
:text-align-vertical :center
|
||||
:height min-input-height
|
||||
:align-items :center
|
||||
:android {:left (+ 15 left)
|
||||
:top 0.5}
|
||||
:ios {:line-height min-input-height
|
||||
:left (+ 9 left)}})
|
||||
|
||||
(def input-emoji-icon
|
||||
{:margin-top 7
|
||||
|
@ -24,7 +24,6 @@
|
||||
(reaction))]))
|
||||
(into {}))))
|
||||
|
||||
|
||||
(register-sub
|
||||
:chat-ui-props
|
||||
(fn [db [_ ui-element chat-id]]
|
||||
@ -87,11 +86,12 @@
|
||||
(register-sub
|
||||
:current-chat-argument-position
|
||||
(fn [db [_ chat-id]]
|
||||
(let [chat-id (or chat-id (@db :current-chat-id))
|
||||
command (subscribe [:selected-chat-command chat-id])
|
||||
input-text (subscribe [:chat :input-text chat-id])]
|
||||
(let [chat-id (or chat-id (@db :current-chat-id))
|
||||
command (subscribe [:selected-chat-command chat-id])
|
||||
input-text (subscribe [:chat :input-text chat-id])
|
||||
seq-arguments (subscribe [:chat :seq-arguments chat-id])]
|
||||
(reaction
|
||||
(input-model/current-chat-argument-position @command @input-text)))))
|
||||
(input-model/current-chat-argument-position @command @input-text @seq-arguments)))))
|
||||
|
||||
(register-sub
|
||||
:chat-parameter-box
|
||||
|
@ -52,36 +52,8 @@
|
||||
^{:key command-key}
|
||||
[command-view index command])]]])
|
||||
|
||||
(defn- invisible-input [{:keys [set-layout-width value]}]
|
||||
(let [input-text (subscribe [:chat :input-text])
|
||||
modified-text (subscribe [:chat :modified-text])]
|
||||
[text {:style style/invisible-input-text
|
||||
:on-layout #(let [w (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-width))]
|
||||
(set-layout-width w))}
|
||||
(utils/safe-trim (or @modified-text @input-text ""))]))
|
||||
|
||||
(defn- input-helper [_]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
(fn [{:keys [command width]}]
|
||||
(when-let [placeholder (cond
|
||||
(= @input-text const/command-char)
|
||||
(i18n/label :t/type-a-command)
|
||||
|
||||
(and command (empty? (:args command)))
|
||||
(get-in command [:command :params 0 :placeholder])
|
||||
|
||||
(and command
|
||||
(= (count (:args command)) 1)
|
||||
(input-model/text-ends-with-space? @input-text))
|
||||
(get-in command [:command :params 1 :placeholder]))]
|
||||
[text {:style (style/input-helper-text width)}
|
||||
placeholder]))))
|
||||
|
||||
(defn- text-field [_]
|
||||
(defn- basic-text-input [_]
|
||||
(let [input-text (subscribe [:chat :input-text])
|
||||
modified-text (subscribe [:chat :modified-text])
|
||||
command (subscribe [:selected-chat-command])
|
||||
sending-in-progress? (subscribe [:chat-ui-props :sending-in-progress?])]
|
||||
(fn [{:keys [set-layout-height height]}]
|
||||
@ -90,7 +62,7 @@
|
||||
:accessibility-label id/chat-message-input
|
||||
:blur-on-submit false
|
||||
:multiline true
|
||||
:default-value (or @modified-text @input-text "")
|
||||
:default-value (or @input-text "")
|
||||
:editable (not @sending-in-progress?)
|
||||
:on-blur #(do (dispatch [:set-chat-ui-props :input-focused? false])
|
||||
(set-layout-height 0))
|
||||
@ -107,21 +79,73 @@
|
||||
(set-layout-height h))
|
||||
:on-selection-change #(let [s (-> (.-nativeEvent %)
|
||||
(.-selection))]
|
||||
;; This will be a bit tricky:
|
||||
;; iOS calls onSelectionChange BEFORE onChangeText, while
|
||||
;; Android calls onChange text first.
|
||||
;; We need some consistency, so we call the callback with a small delay:
|
||||
(js/setTimeout
|
||||
(fn [] (dispatch [:set-chat-ui-props :selection {:start (.-start s)
|
||||
:end (.-end s)}]))
|
||||
20))
|
||||
:on-submit-editing #(do (dispatch [:set-chat-ui-props :sending-in-progress? true])
|
||||
(dispatch [:send-current-message]))
|
||||
(when (and (= (.-end s) 10)
|
||||
(get command [:command :sequential-params]))
|
||||
(dispatch [:chat-input-focus :seq-input-ref])))
|
||||
:on-submit-editing #(dispatch [:send-current-message])
|
||||
:on-focus #(do (dispatch [:set-chat-ui-props :input-focused? true])
|
||||
(dispatch [:set-chat-ui-props :show-emoji? false]))
|
||||
:style (style/input-view height)
|
||||
:placeholder-text-color style/color-input-helper-placeholder}])))
|
||||
|
||||
(defn- invisible-input [{:keys [set-layout-width value]}]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
[text {:style style/invisible-input-text
|
||||
:on-layout #(let [w (-> (.-nativeEvent %)
|
||||
(.-layout)
|
||||
(.-width))]
|
||||
(set-layout-width w))}
|
||||
(or @input-text "")]))
|
||||
|
||||
(defn- input-helper [_]
|
||||
(let [input-text (subscribe [:chat :input-text])]
|
||||
(fn [{:keys [command width]}]
|
||||
(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)
|
||||
(i18n/label :t/type-a-command)
|
||||
|
||||
(and command (empty? real-args))
|
||||
(get-in command [:command :params 0 :placeholder])
|
||||
|
||||
(and command
|
||||
(= (count real-args) 1)
|
||||
(input-model/text-ends-with-space? @input-text))
|
||||
(get-in command [:command :params 1 :placeholder]))]
|
||||
[text {:style (style/input-helper-text width)}
|
||||
placeholder]))))))
|
||||
|
||||
(defn get-options [type]
|
||||
(case (keyword type)
|
||||
:phone {:keyboard-type "phone-pad"}
|
||||
:password {:secure-text-entry true}
|
||||
:number {:keyboard-type "numeric"}
|
||||
nil))
|
||||
|
||||
(defn- seq-input [_]
|
||||
(let [command (subscribe [:selected-chat-command])
|
||||
arg-pos (subscribe [:current-chat-argument-position])
|
||||
seq-arg-input-text (subscribe [:chat :seq-argument-input-text])]
|
||||
(fn [{:keys [command-width]}]
|
||||
(when (get-in @command [:command :sequential-params])
|
||||
(let [{:keys [placeholder hidden type]} (get-in @command [:command :params @arg-pos])]
|
||||
[text-input (merge {:ref #(dispatch [:set-chat-ui-props :seq-input-ref %])
|
||||
:style (style/input-password-text command-width)
|
||||
:default-value (or @seq-arg-input-text "")
|
||||
:on-change-text #(do (dispatch [:set-chat-seq-arg-input-text %])
|
||||
(dispatch [:set-chat-ui-props :validation-messages nil]))
|
||||
:secure-text-entry hidden
|
||||
:placeholder placeholder
|
||||
:blur-on-submit false
|
||||
:on-submit-editing (fn []
|
||||
(when-not (str/blank? @seq-arg-input-text)
|
||||
(dispatch [:send-seq-argument]))
|
||||
(js/setTimeout
|
||||
#(dispatch [:chat-input-focus :seq-input-ref])
|
||||
100))}
|
||||
(get-options type))])))))
|
||||
|
||||
(defn input-view [_]
|
||||
(let [component (r/current-component)
|
||||
set-layout-width #(r/set-state component {:width %})
|
||||
@ -137,11 +161,12 @@
|
||||
(let [{:keys [width height]} (r/state component)
|
||||
command @command]
|
||||
[animated-view {:style (style/input-root height anim-margin)}
|
||||
[text-field {:set-layout-height set-layout-height
|
||||
:height height}]
|
||||
[basic-text-input {:set-layout-height set-layout-height
|
||||
:height height}]
|
||||
[invisible-input {:set-layout-width set-layout-width}]
|
||||
[input-helper {:command command
|
||||
:width width}]
|
||||
[seq-input {:command-width width}]
|
||||
(if-not command
|
||||
[touchable-highlight
|
||||
{:on-press #(do (dispatch [:toggle-chat-ui-props :show-emoji?])
|
||||
@ -152,21 +177,29 @@
|
||||
{:on-press #(do (dispatch [:set-chat-input-text nil])
|
||||
(dispatch [:set-chat-input-metadata nil])
|
||||
(dispatch [:set-chat-ui-props :result-box nil])
|
||||
(dispatch [:set-chat-ui-props :validation-messages nil]))}
|
||||
(dispatch [:set-chat-ui-props :validation-messages nil])
|
||||
(dispatch [:clear-seq-arguments]))}
|
||||
[view style/input-clear-container
|
||||
[icon :close_gray style/input-clear-icon]]])]))})))
|
||||
|
||||
(defview input-container [{:keys [anim-margin]}]
|
||||
[command-completion [:command-completion]
|
||||
selected-command [:selected-chat-command]
|
||||
input-text [:chat :input-text]]
|
||||
input-text [:chat :input-text]
|
||||
seq-arg-input-text [:chat :seq-argument-input-text]]
|
||||
[view style/input-container
|
||||
[input-view {:anim-margin anim-margin}]
|
||||
(when (and (not (str/blank? input-text))
|
||||
(or (not selected-command)
|
||||
(some #{:complete :less-than-needed} [command-completion])))
|
||||
[touchable-highlight {:on-press #(do (dispatch [:set-chat-ui-props :sending-in-progress? true])
|
||||
(dispatch [:send-current-message]))}
|
||||
[touchable-highlight {:on-press #(if (get-in selected-command [:command :sequential-params])
|
||||
(do
|
||||
(when-not (str/blank? seq-arg-input-text)
|
||||
(dispatch [:send-seq-argument]))
|
||||
(js/setTimeout
|
||||
(fn [] (dispatch [:chat-input-focus :seq-input-ref]))
|
||||
100))
|
||||
(dispatch [:send-current-message]))}
|
||||
[view style/send-message-container
|
||||
[icon :arrow_top style/send-message-icon]]])])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user