remove commands before replacement by gui commands
Signed-off-by: yenda <eric@status.im>
This commit is contained in:
parent
0b802ec456
commit
94c7953f30
|
@ -1,154 +0,0 @@
|
|||
(ns status-im.chat.commands.core
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.impl.transactions :as transactions]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(def register
|
||||
"Register of all commands. Whenever implementing a new command,
|
||||
provide the implementation in the `status-im.chat.commands.impl.*` ns,
|
||||
and add its instance here."
|
||||
#{(transactions/PersonalSendCommand.)
|
||||
(transactions/PersonalRequestCommand.)})
|
||||
|
||||
(def command-id (juxt protocol/id protocol/scope))
|
||||
|
||||
(defn command-name
|
||||
"Given the command instance, returns command name as displayed in chat input,
|
||||
with leading `/` character."
|
||||
[type]
|
||||
(str chat.constants/command-char (protocol/id type)))
|
||||
|
||||
(defn command-description
|
||||
"Returns description for the command."
|
||||
[type]
|
||||
(protocol/description type))
|
||||
|
||||
(defn accessibility-label
|
||||
"Returns accessibility button label for command, derived from its id"
|
||||
[type]
|
||||
(keyword (str (protocol/id type) "-button")))
|
||||
|
||||
(defn- contact->address [contact]
|
||||
(str "0x" (ethereum/public-key->address contact)))
|
||||
|
||||
(defn add-chat-contacts
|
||||
"Enrich command-message by adding contact list of the current private or group chat"
|
||||
[contacts {:keys [public? group-chat] :as command-message}]
|
||||
(cond
|
||||
public? command-message
|
||||
group-chat (assoc command-message :contacts (map contact->address contacts))
|
||||
:else (assoc command-message :contact (contact->address (first contacts)))))
|
||||
|
||||
(defn enrich-command-message-for-events
|
||||
"adds new pairs to command-message to be consumed by extension events"
|
||||
[db {:keys [chat-id] :as command-message}]
|
||||
(let [{:keys [contacts public? group-chat]} (get-in db [:chats chat-id])]
|
||||
(add-chat-contacts contacts (assoc command-message :public? public? :group-chat group-chat))))
|
||||
|
||||
(defn generate-short-preview
|
||||
"Returns short preview for command"
|
||||
[{:keys [type]} command-message]
|
||||
(protocol/short-preview type command-message))
|
||||
|
||||
(defn generate-preview
|
||||
"Returns preview for command"
|
||||
[{:keys [type]} command-message]
|
||||
(protocol/preview type command-message))
|
||||
|
||||
(defn- add-exclusive-choices [initial-scope exclusive-choices]
|
||||
(reduce (fn [scopes-set exclusive-choices]
|
||||
(reduce (fn [scopes-set scope]
|
||||
(let [exclusive-match (set/intersection scope exclusive-choices)]
|
||||
(if (seq exclusive-match)
|
||||
(reduce conj
|
||||
(disj scopes-set scope)
|
||||
(map (partial conj
|
||||
(set/difference scope exclusive-match))
|
||||
exclusive-match))
|
||||
scopes-set)))
|
||||
scopes-set
|
||||
scopes-set))
|
||||
#{initial-scope}
|
||||
exclusive-choices))
|
||||
|
||||
(defn index-commands
|
||||
"Takes collecton of things implementing the command protocol, and
|
||||
correctly indexes them by their composite ids and access scopes."
|
||||
[commands]
|
||||
(let [id->command (reduce (fn [acc command]
|
||||
(assoc acc (command-id command)
|
||||
{:type command
|
||||
:params (into [] (protocol/parameters command))}))
|
||||
{}
|
||||
commands)
|
||||
access-scope->command-id (reduce-kv (fn [acc command-id {:keys [type]}]
|
||||
(let [access-scopes (add-exclusive-choices
|
||||
(protocol/scope type)
|
||||
protocol/or-scopes)]
|
||||
(reduce (fn [acc access-scope]
|
||||
(update acc
|
||||
access-scope
|
||||
(fnil conj #{})
|
||||
command-id))
|
||||
acc
|
||||
access-scopes)))
|
||||
{}
|
||||
id->command)]
|
||||
{:id->command id->command
|
||||
:access-scope->command-id access-scope->command-id}))
|
||||
|
||||
(fx/defn load-commands
|
||||
"Takes collection of things implementing the command protocol and db,
|
||||
correctly indexes them and adds them to db in a way that preserves existing commands"
|
||||
[{:keys [db]} commands]
|
||||
(let [{:keys [id->command access-scope->command-id]} (index-commands commands)]
|
||||
{:db (-> db
|
||||
(update :id->command merge id->command)
|
||||
(update :access-scope->command-id #(merge-with (fnil into #{}) % access-scope->command-id)))}))
|
||||
|
||||
(defn remove-command
|
||||
"Remove command form db, correctly updating all indexes"
|
||||
[command {:keys [db]}]
|
||||
(let [id (command-id command)]
|
||||
{:db (-> db
|
||||
(update :id->command dissoc id)
|
||||
(update :access-scope->command-id (fn [access-scope->command-id]
|
||||
(reduce (fn [acc [scope command-ids-set]]
|
||||
(if (command-ids-set id)
|
||||
(if (= 1 (count command-ids-set))
|
||||
acc
|
||||
(assoc acc scope (disj command-ids-set id)))
|
||||
(assoc acc scope command-ids-set)))
|
||||
{}
|
||||
access-scope->command-id))))}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-commands
|
||||
(fn [cofx [_ commands]]
|
||||
(load-commands commands cofx)))
|
||||
|
||||
(defn chat-commands
|
||||
"Takes `id->command`, `access-scope->command-id` and `chat` parameters and returns
|
||||
entries map of `id->command` map eligible for given chat.
|
||||
Note that the result map is keyed just by `protocol/id` of command entries,
|
||||
not the unique composite ids of the global `id->command` map.
|
||||
That's because this function is already returning local commands for particular
|
||||
chat and locally, they should always have unique `protocol/id`."
|
||||
[id->command access-scope->command-id {:keys [chat-id group-chat public?]}]
|
||||
(let [global-access-scope (cond-> #{}
|
||||
(not group-chat) (conj :personal-chats)
|
||||
(and group-chat (not public?)) (conj :group-chats)
|
||||
public? (conj :public-chats))
|
||||
chat-access-scope #{chat-id}]
|
||||
;;TODO disable commands temporary for v1
|
||||
{}
|
||||
#_(reduce (fn [acc command-id]
|
||||
(let [{:keys [type] :as command-props} (get id->command command-id)]
|
||||
(assoc acc (protocol/id type) command-props)))
|
||||
{}
|
||||
(concat (get access-scope->command-id global-access-scope)
|
||||
(get access-scope->command-id chat-access-scope)))))
|
|
@ -1,465 +0,0 @@
|
|||
(ns status-im.chat.commands.impl.transactions
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.chat.commands.impl.transactions.styles
|
||||
:as
|
||||
transactions-styles]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.svgimage :as svgimage]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.ethereum.abi-spec :as abi-spec])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
;; common `send/request` functionality
|
||||
|
||||
(defn- render-asset [{:keys [name symbol amount decimals icon color] :as asset}]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/set-command-parameter (wallet.utils/display-symbol asset)])}
|
||||
[react/view transactions-styles/asset-container
|
||||
[react/view transactions-styles/asset-main
|
||||
(if icon
|
||||
[react/image {:source (:source icon)
|
||||
:style transactions-styles/asset-icon}]
|
||||
[react/view {:style transactions-styles/asset-icon}
|
||||
[chat-icon/custom-icon-view-list name color 30]])
|
||||
[react/text (wallet.utils/display-symbol asset)]
|
||||
[react/text {:style transactions-styles/asset-name} name]]
|
||||
;;TODO(goranjovic) : temporarily disabled to fix https://github.com/status-im/status-react/issues/4963
|
||||
;;until the resolution of https://github.com/status-im/status-react/issues/4972
|
||||
#_[react/text {:style transactions-styles/asset-balance}
|
||||
(str (money/internal->formatted amount symbol decimals))]]])
|
||||
|
||||
(defn- render-nft-asset [{:keys [name symbol amount] :as asset}]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/set-command-parameter (clojure.core/name symbol)])}
|
||||
[react/view transactions-styles/asset-container
|
||||
[react/view transactions-styles/asset-main
|
||||
[react/image {:source (-> asset :icon :source)
|
||||
:style transactions-styles/asset-icon}]
|
||||
[react/text name]]
|
||||
[react/text {:style {:font-size 16
|
||||
:color colors/gray
|
||||
:padding-right 14}}
|
||||
(money/to-fixed amount)]]])
|
||||
|
||||
(def assets-separator [react/view transactions-styles/asset-separator])
|
||||
|
||||
(defn choose-asset [nft?] [react/view])
|
||||
;;TODO we'll need to specify address here
|
||||
#_(letsubs [assets [:wallet/visible-assets-with-amount]]
|
||||
[react/view
|
||||
[list/flat-list {:data (filter #(if nft?
|
||||
(:nft? %)
|
||||
(not (:nft? %)))
|
||||
assets)
|
||||
:key-fn (comp name :symbol)
|
||||
:render-fn (if nft?
|
||||
render-nft-asset
|
||||
render-asset)
|
||||
:enableEmptySections true
|
||||
:separator assets-separator
|
||||
:keyboardShouldPersistTaps :always
|
||||
:bounces false}]])
|
||||
|
||||
(defn choose-asset-suggestion []
|
||||
[choose-asset false])
|
||||
|
||||
(defn personal-send-request-short-preview
|
||||
[label-key {:keys [content]}]
|
||||
(let [{:keys [amount coin]} (:params content)]
|
||||
[react/text {:number-of-lines 1}
|
||||
(i18n/label label-key {:amount amount
|
||||
:asset (wallet.utils/display-symbol coin)})]))
|
||||
|
||||
(def personal-send-request-params
|
||||
[{:id :asset
|
||||
:type :text
|
||||
:placeholder (i18n/label :t/send-request-currency)
|
||||
:suggestions choose-asset-suggestion}
|
||||
{:id :amount
|
||||
:type :number
|
||||
:placeholder (i18n/label :t/send-request-amount)}])
|
||||
|
||||
(defview choose-nft-token []
|
||||
(letsubs [{:keys [input-params]} [:chats/selected-chat-command]
|
||||
collectibles [:collectibles]]
|
||||
(let [collectible-tokens (get collectibles (keyword (:symbol input-params)))]
|
||||
[react/view {:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-vertical 11}
|
||||
(map
|
||||
(fn [[id {:keys [name image_url]}]]
|
||||
[react/touchable-highlight
|
||||
{:key id
|
||||
:on-press #(re-frame/dispatch [:chat.ui/set-command-parameter (str id)])}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center
|
||||
:margin-left 10
|
||||
:border-radius 2
|
||||
:border-width 1
|
||||
:border-color colors/gray}
|
||||
[svgimage/svgimage {:style {:width 100
|
||||
:height 100
|
||||
:margin-left 20
|
||||
:margin-right 20}
|
||||
:source {:uri image_url}}]
|
||||
[react/text name]]])
|
||||
collectible-tokens)])))
|
||||
|
||||
(defview nft-token [{{:keys [name image_url]} :token}]
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[svgimage/svgimage {:style {:width 100
|
||||
:height 100}
|
||||
:source {:uri image_url}}]
|
||||
[react/text name]])
|
||||
|
||||
;;TODO(goranjovic): currently we only allow tokens which are enabled in Manage assets here
|
||||
;; because balances are only fetched for them. Revisit this decision with regard to battery/network consequences
|
||||
;; if we were to update all balances.
|
||||
(defn- allowed-assets [{:keys [chain multiaccount] :as db}]
|
||||
(let [all-tokens (:wallet/all-tokens db)
|
||||
chain-keyword (keyword chain)
|
||||
{:keys [symbol symbol-display decimals]} (tokens/native-currency chain-keyword)
|
||||
visible-tokens (get-in multiaccount [:settings :wallet :visible-tokens chain-keyword])]
|
||||
(into {(name (or symbol-display symbol)) decimals}
|
||||
(comp (filter #(and (not (:nft? %))
|
||||
(contains? visible-tokens (:symbol %))))
|
||||
(map (juxt (comp name :symbol) :decimals)))
|
||||
(tokens/tokens-for all-tokens chain-keyword))))
|
||||
|
||||
(defn- personal-send-request-validation [{:keys [asset amount]} {:keys [db]}]
|
||||
(let [asset-decimals (get (allowed-assets db) asset)]
|
||||
(cond
|
||||
|
||||
(not asset-decimals)
|
||||
{:title (i18n/label :t/send-request-invalid-asset)
|
||||
:description (i18n/label :t/send-request-unknown-token {:asset asset})}
|
||||
|
||||
(not amount)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-must-be-specified)}
|
||||
|
||||
:else
|
||||
(let [sanitised-str (string/replace amount #"," ".")
|
||||
portions (string/split sanitised-str ".")
|
||||
decimals (count (get portions 1))
|
||||
amount-string (str amount)
|
||||
amount (js/Number sanitised-str)]
|
||||
(cond
|
||||
|
||||
(or (js/isNaN amount)
|
||||
(> (count portions) 2)
|
||||
(re-matches #".+(\.|,)$" amount-string)
|
||||
;; check if non-decimal number
|
||||
(re-matches #"0[\dbxo][\d\.]*" amount-string))
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}
|
||||
|
||||
(and decimals (> decimals asset-decimals))
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-max-decimals
|
||||
{:asset-decimals asset-decimals})})))))
|
||||
|
||||
;; `/send` command
|
||||
|
||||
(defview send-status [tx-hash outgoing]
|
||||
(letsubs [{:keys [exists? confirmed?]} [:chats/transaction-status tx-hash]]
|
||||
[react/touchable-highlight {:on-press #(when exists?
|
||||
(re-frame/dispatch [:wallet.ui/show-transaction-details tx-hash]))}
|
||||
[react/view transactions-styles/command-send-status-container
|
||||
[vector-icons/tiny-icon (if confirmed?
|
||||
:tiny-icons/tiny-check
|
||||
:tiny-icons/tiny-pending)
|
||||
{:color (if outgoing
|
||||
colors/blue-light
|
||||
colors/blue)
|
||||
:container-style (transactions-styles/command-send-status-icon outgoing)}]
|
||||
[react/view
|
||||
[react/text {:style (transactions-styles/command-send-status-text outgoing)}
|
||||
(i18n/label (cond
|
||||
confirmed? :status-confirmed
|
||||
exists? :status-pending
|
||||
:else :status-tx-not-found))]]]]))
|
||||
|
||||
(defn transaction-status [{:keys [tx-hash outgoing]}]
|
||||
[send-status tx-hash outgoing])
|
||||
|
||||
(defview send-preview
|
||||
[{:keys [content timestamp-str outgoing group-chat]}]
|
||||
(letsubs [network [:chain-name]
|
||||
all-tokens [:wallet/all-tokens]]
|
||||
(let [{{:keys [amount fiat-amount tx-hash asset currency] send-network :network} :params} content
|
||||
recipient-name (get-in content [:params :bot-db :public :recipient])
|
||||
network-mismatch? (and (seq send-network) (not= network send-network))
|
||||
token (tokens/asset-for all-tokens (keyword send-network) (keyword asset))]
|
||||
[react/view transactions-styles/command-send-message-view
|
||||
[react/view
|
||||
[react/view transactions-styles/command-send-amount-row
|
||||
[react/view transactions-styles/command-send-amount
|
||||
[react/nested-text {:style (transactions-styles/command-send-amount-text outgoing)}
|
||||
amount
|
||||
[{:style (transactions-styles/command-amount-currency-separator outgoing)}
|
||||
"."]
|
||||
[{:style (transactions-styles/command-send-currency-text outgoing)}
|
||||
(wallet.utils/display-symbol token)]]]]
|
||||
(when (and fiat-amount
|
||||
platform/mobile?
|
||||
;;NOTE(goranjovic) - have to hide cross network asset fiat value until we can support
|
||||
;; multiple chain prices simultaneously
|
||||
(not network-mismatch?))
|
||||
[react/view transactions-styles/command-send-fiat-amount
|
||||
[react/text {:style (transactions-styles/command-send-fiat-amount-text outgoing)}
|
||||
(str "~ " fiat-amount " " (or currency (i18n/label :usd-currency)))]])
|
||||
(when (and group-chat
|
||||
recipient-name)
|
||||
[react/text {:style transactions-styles/command-send-recipient-text}
|
||||
(i18n/label :send-sending-to {:recipient-name recipient-name})])
|
||||
[react/view
|
||||
[react/text {:style (transactions-styles/command-send-timestamp outgoing)}
|
||||
(str (i18n/label :sent-at) " " timestamp-str)]]
|
||||
(when platform/mobile?
|
||||
[send-status tx-hash outgoing])
|
||||
(when network-mismatch?
|
||||
[react/text send-network])]])))
|
||||
|
||||
;; TODO(goranjovic) - update to include tokens in https://github.com/status-im/status-react/issues/3233
|
||||
(defn- transaction-details [contact symbol]
|
||||
(-> contact
|
||||
(select-keys [:name :address :public-key])
|
||||
(assoc :symbol symbol
|
||||
:gas (ethereum/estimate-gas symbol)
|
||||
:from-chat? true)))
|
||||
|
||||
(defn- inject-network-info [parameters {:keys [db]}]
|
||||
(assoc parameters :network (:chain db)))
|
||||
|
||||
(defn- inject-coin-info [{:keys [network asset] :as parameters} {:keys [db]}]
|
||||
(let [all-tokens (:wallet/all-tokens db)
|
||||
coin (when (and network asset)
|
||||
(tokens/asset-for all-tokens (keyword network) (keyword asset)))]
|
||||
(assoc parameters :coin coin)))
|
||||
|
||||
(defn get-currency [db]
|
||||
(or (get-in db [:multiaccount :settings :wallet :currency]) :usd))
|
||||
|
||||
(defn- inject-price-info [{:keys [amount asset] :as parameters} {:keys [db]}]
|
||||
(let [currency (-> db
|
||||
get-currency
|
||||
name
|
||||
string/upper-case)]
|
||||
(assoc parameters
|
||||
:fiat-amount (money/fiat-amount-value (string/replace amount #"," ".")
|
||||
(keyword asset)
|
||||
(keyword currency)
|
||||
(:prices db))
|
||||
:currency currency)))
|
||||
|
||||
(defn- params-unchanged? [send-message request-message]
|
||||
(and (= (get-in send-message [:content :params :asset])
|
||||
(get-in request-message [:content :params :asset]))
|
||||
(= (get-in send-message [:content :params :amount])
|
||||
(get-in request-message [:content :params :amount]))))
|
||||
|
||||
(deftype PersonalSendCommand []
|
||||
protocol/Command
|
||||
(id [_] "send")
|
||||
(scope [_] #{:personal-chats})
|
||||
(description [_] (i18n/label :t/send-command-payment))
|
||||
(parameters [_] personal-send-request-params)
|
||||
(validate [_ parameters cofx]
|
||||
;; Only superficial/formatting validation, "real validation" will be performed
|
||||
;; by the wallet, where we yield control in the next step
|
||||
(personal-send-request-validation parameters cofx))
|
||||
(on-send [_ {:keys [chat-id] :as send-message} {:keys [db] :as cofx}]
|
||||
(when-let [responding-to (get-in db [:chats chat-id :metadata :responding-to-command])]
|
||||
(when-let [request-message (get-in db [:chats chat-id :messages responding-to])]
|
||||
(when (params-unchanged? send-message request-message)
|
||||
(let [updated-request-message (assoc-in request-message [:content :params :answered?] true)]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:chats chat-id :messages responding-to] updated-request-message)}
|
||||
(messages-store/save-message updated-request-message)))))))
|
||||
(on-receive [_ command-message cofx])
|
||||
(short-preview [_ command-message]
|
||||
(personal-send-request-short-preview :command-sending command-message))
|
||||
(preview [_ command-message]
|
||||
(send-preview command-message))
|
||||
protocol/Yielding
|
||||
(yield-control [_ {{{amount :amount asset :asset} :params} :content} {:keys [db] :as cofx}]
|
||||
(let [{:keys [symbol decimals address]} (tokens/asset-for (:wallet/all-tokens db) (keyword (:chain db)) (keyword asset))
|
||||
{:keys [value]} (wallet.db/parse-amount amount decimals)
|
||||
current-chat-id (:current-chat-id db)
|
||||
amount-hex (str "0x" (abi-spec/number-to-hex (money/formatted->internal value symbol decimals)))
|
||||
to (ethereum/public-key->address current-chat-id)
|
||||
to-norm (ethereum/normalized-hex (if (= symbol :ETH) to address))
|
||||
tx-obj (if (= symbol :ETH)
|
||||
{:to to-norm
|
||||
:value amount-hex}
|
||||
{:to to-norm
|
||||
:data (abi-spec/encode "transfer(address,uint256)" [to amount-hex])})]
|
||||
(signing/sign cofx {:tx-obj tx-obj
|
||||
:on-result [:chat/send-transaction-result current-chat-id {:address to-norm
|
||||
:asset (name symbol)
|
||||
:amount amount}]})))
|
||||
protocol/EnhancedParameters
|
||||
(enhance-send-parameters [_ parameters cofx]
|
||||
(-> parameters
|
||||
(inject-network-info cofx)
|
||||
(inject-coin-info cofx)
|
||||
(inject-price-info cofx)))
|
||||
(enhance-receive-parameters [_ parameters cofx]
|
||||
(-> parameters
|
||||
(inject-coin-info cofx)
|
||||
(inject-price-info cofx))))
|
||||
|
||||
;; `/request` command
|
||||
|
||||
(def request-message-icon-scale-delay 600)
|
||||
|
||||
(def min-scale 1)
|
||||
(def max-scale 1.3)
|
||||
|
||||
(defn button-animation [val to-value loop? answered?]
|
||||
(animation/anim-sequence
|
||||
[(animation/anim-delay
|
||||
(if (and @loop? (not @answered?))
|
||||
request-message-icon-scale-delay
|
||||
0))
|
||||
(animation/spring val {:toValue to-value
|
||||
:useNativeDriver true})]))
|
||||
|
||||
(defn request-button-animation-logic
|
||||
[{:keys [to-value val loop? answered?] :as context}]
|
||||
(animation/start
|
||||
(button-animation val to-value loop? answered?)
|
||||
#(if (and @loop? (not @answered?))
|
||||
(let [new-value (if (= to-value min-scale) max-scale min-scale)
|
||||
context' (assoc context :to-value new-value)]
|
||||
(request-button-animation-logic context'))
|
||||
(animation/start
|
||||
(button-animation val min-scale loop? answered?)))))
|
||||
|
||||
(defn request-button-label
|
||||
"The request button label will be in the form of `request-the-command-name`"
|
||||
[command-name]
|
||||
(keyword (str "request-" (name command-name))))
|
||||
|
||||
(defn request-button [message-id _ on-press-handler]
|
||||
(let [scale-anim-val (animation/create-value min-scale)
|
||||
answered? (re-frame/subscribe [:is-request-answered? message-id])
|
||||
loop? (reagent/atom true)
|
||||
context {:to-value max-scale
|
||||
:val scale-anim-val
|
||||
:answered? answered?
|
||||
:loop? loop?}]
|
||||
(reagent/create-class
|
||||
{:display-name "request-button"
|
||||
:component-did-mount
|
||||
(if (or (nil? on-press-handler) @answered?) (fn []) #(request-button-animation-logic context))
|
||||
:component-will-unmount
|
||||
#(reset! loop? false)
|
||||
:reagent-render
|
||||
(fn [message-id {command-icon :icon :as command} on-press-handler]
|
||||
(when command
|
||||
[react/touchable-highlight
|
||||
{:on-press on-press-handler
|
||||
:style transactions-styles/command-request-image-touchable
|
||||
:accessibility-label (request-button-label (:name command))}
|
||||
[react/animated-view {:style (transactions-styles/command-request-image-view command scale-anim-val)}
|
||||
(when command-icon
|
||||
[react/icon command-icon transactions-styles/command-request-image])]]))})))
|
||||
|
||||
(defview request-preview
|
||||
[{:keys [message-id content outgoing timestamp timestamp-str group-chat]}]
|
||||
(letsubs [id->command [:chats/id->command]
|
||||
network [:chain-name]
|
||||
prices [:prices]]
|
||||
(let [{:keys [amount asset fiat-amount currency answered?] request-network :network} (:params content)
|
||||
network-mismatch? (and request-network (not= request-network network))
|
||||
command (get id->command ["send" #{:personal-chats}])
|
||||
markup [react/view (transactions-styles/command-request-message-view outgoing)
|
||||
[react/view
|
||||
[react/text {:style (transactions-styles/command-request-header-text outgoing)}
|
||||
(i18n/label :transaction-request)]]
|
||||
[react/view transactions-styles/command-request-row
|
||||
[react/nested-text {:style (transactions-styles/command-request-amount-text outgoing)}
|
||||
amount
|
||||
[{:style (transactions-styles/command-amount-currency-separator outgoing)}
|
||||
"."]
|
||||
[{:style (transactions-styles/command-request-currency-text outgoing)}
|
||||
asset]]]
|
||||
(when (and platform/mobile?
|
||||
;;NOTE(goranjovic) - have to hide cross network asset fiat value until we can support
|
||||
;; multiple chain prices simultaneously
|
||||
(not network-mismatch?))
|
||||
[react/view transactions-styles/command-request-fiat-amount-row
|
||||
[react/text {:style (transactions-styles/command-request-fiat-amount-text outgoing)}
|
||||
(str "~ " fiat-amount " " (or currency (i18n/label :usd-currency)))]])
|
||||
(when network-mismatch?
|
||||
[react/text {:style transactions-styles/command-request-network-text}
|
||||
(str (i18n/label :on) " " request-network)])
|
||||
[react/view transactions-styles/command-request-timestamp-row
|
||||
[react/text {:style (transactions-styles/command-request-timestamp-text outgoing)}
|
||||
(str
|
||||
(datetime/timestamp->mini-date timestamp)
|
||||
" "
|
||||
(i18n/label :at)
|
||||
" "
|
||||
timestamp-str)]]
|
||||
(when (and (not outgoing)
|
||||
platform/mobile?)
|
||||
[react/view
|
||||
[react/view transactions-styles/command-request-separator-line]
|
||||
[react/view transactions-styles/command-request-button
|
||||
[react/text {:style (transactions-styles/command-request-button-text answered?)}
|
||||
(i18n/label (if answered? :command-button-sent :command-button-send))]]])]]
|
||||
(if (and (not network-mismatch?)
|
||||
(not outgoing)
|
||||
(not answered?))
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/select-chat-input-command
|
||||
command [(or asset "ETH") amount] message-id])}
|
||||
markup]
|
||||
markup))))
|
||||
|
||||
(deftype PersonalRequestCommand []
|
||||
protocol/Command
|
||||
(id [_] "request")
|
||||
(scope [_] #{:personal-chats})
|
||||
(description [_] (i18n/label :t/request-command-payment))
|
||||
(parameters [_] personal-send-request-params)
|
||||
(validate [_ parameters cofx]
|
||||
(personal-send-request-validation parameters cofx))
|
||||
(on-send [_ _ _])
|
||||
(on-receive [_ _ _])
|
||||
(short-preview [_ command-message]
|
||||
(personal-send-request-short-preview :command-requesting command-message))
|
||||
(preview [_ command-message]
|
||||
(request-preview command-message))
|
||||
protocol/EnhancedParameters
|
||||
(enhance-send-parameters [_ parameters cofx]
|
||||
(-> parameters
|
||||
(inject-network-info cofx)
|
||||
(inject-coin-info cofx)
|
||||
(inject-price-info cofx)))
|
||||
(enhance-receive-parameters [_ parameters cofx]
|
||||
(-> parameters
|
||||
(inject-coin-info cofx)
|
||||
(inject-price-info cofx))))
|
|
@ -1,185 +0,0 @@
|
|||
(ns status-im.chat.commands.impl.transactions.styles
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def asset-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:padding-vertical 11})
|
||||
|
||||
(def asset-main
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def asset-icon
|
||||
{:width 30
|
||||
:height 30
|
||||
:margin-left 14
|
||||
:margin-right 12})
|
||||
|
||||
(def asset-name
|
||||
{:color colors/gray
|
||||
:padding-left 4})
|
||||
|
||||
(def asset-balance
|
||||
{:color colors/gray
|
||||
:padding-right 14})
|
||||
|
||||
(def asset-separator
|
||||
{:height 1
|
||||
:background-color colors/black-transparent
|
||||
:margin-left 56})
|
||||
|
||||
(def command-send-status-container
|
||||
{:margin-top 6
|
||||
:flex-direction :row})
|
||||
|
||||
(defn command-send-status-icon
|
||||
[outgoing]
|
||||
{:background-color (if outgoing
|
||||
colors/black-transparent
|
||||
colors/blue-light)
|
||||
:width 24
|
||||
:height 24
|
||||
:border-radius 16
|
||||
:padding-top 4
|
||||
:padding-left 4})
|
||||
|
||||
(defn command-send-status-text
|
||||
[outgoing]
|
||||
{:typography :caption
|
||||
:color (if outgoing
|
||||
colors/white-transparent
|
||||
colors/blue)
|
||||
:margin-top 4
|
||||
:margin-left 6})
|
||||
|
||||
(def command-send-message-view
|
||||
{:flex-direction :column
|
||||
:align-items :flex-start})
|
||||
|
||||
(def command-send-amount-row
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(def command-send-amount
|
||||
{:flex-direction :column
|
||||
:align-items :flex-end
|
||||
:max-width 250})
|
||||
|
||||
(defn command-send-amount-text
|
||||
[outgoing]
|
||||
{:font-size 22
|
||||
:line-height 28
|
||||
:font-weight "600"
|
||||
:color (if outgoing colors/white colors/blue)})
|
||||
|
||||
(def command-send-currency
|
||||
{:flex-direction :column
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn command-amount-currency-separator [outgoing]
|
||||
{:opacity 0
|
||||
:color (if outgoing colors/blue colors/blue-light)})
|
||||
|
||||
(defn command-send-currency-text [outgoing]
|
||||
{:font-size 22
|
||||
:margin-left 4
|
||||
:color (if outgoing colors/white-transparent colors/gray)})
|
||||
|
||||
(defn command-request-currency-text [outgoing]
|
||||
{:font-size 22
|
||||
:color (if outgoing colors/white-transparent colors/gray)})
|
||||
|
||||
(defn command-request-timestamp-text [outgoing]
|
||||
{:font-size 12
|
||||
:color (if outgoing colors/white-transparent colors/gray)})
|
||||
|
||||
(def command-send-fiat-amount
|
||||
{:flex-direction :column
|
||||
:justify-content :flex-end
|
||||
:margin-top 6})
|
||||
|
||||
(defn command-send-fiat-amount-text [outgoing]
|
||||
{:typography :caption
|
||||
:color (if outgoing colors/white colors/black)})
|
||||
|
||||
(def command-send-recipient-text
|
||||
{:color colors/blue
|
||||
:font-size 14})
|
||||
|
||||
(defn command-send-timestamp [outgoing]
|
||||
{:color (if outgoing colors/white-transparent colors/gray)
|
||||
:margin-top 6
|
||||
:font-size 12})
|
||||
|
||||
(def command-request-image-touchable
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:right -8
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:width 48
|
||||
:height 48})
|
||||
|
||||
(defn command-request-image-view [command scale]
|
||||
{:width 32
|
||||
:height 32
|
||||
:border-radius 16
|
||||
:background-color (:color command)
|
||||
:transform [{:scale scale}]})
|
||||
|
||||
(def command-request-image
|
||||
{:position :absolute
|
||||
:top 9
|
||||
:left 10
|
||||
:width 12
|
||||
:height 13})
|
||||
|
||||
(defn command-request-message-view [outgoing]
|
||||
{:border-radius 14
|
||||
:padding-vertical 4
|
||||
:background-color (if outgoing colors/blue colors/blue-light)})
|
||||
|
||||
(defn command-request-header-text [outgoing]
|
||||
{:font-size 12
|
||||
:color (if outgoing colors/white-transparent colors/gray)})
|
||||
|
||||
(def command-request-row
|
||||
{:flex-direction :row
|
||||
:margin-top 6})
|
||||
|
||||
(defn command-request-amount-text [outgoing]
|
||||
{:font-size 22
|
||||
:color (if outgoing colors/white colors/black)})
|
||||
|
||||
(def command-request-separator-line
|
||||
{:background-color colors/black-transparent
|
||||
:height 1
|
||||
:border-radius 8
|
||||
:margin-top 10})
|
||||
|
||||
(def command-request-button
|
||||
{:align-items :center
|
||||
:padding-top 8})
|
||||
|
||||
(defn command-request-button-text [answered?]
|
||||
{:color (if answered? colors/gray colors/blue)})
|
||||
|
||||
(def command-request-fiat-amount-row
|
||||
{:margin-top 6})
|
||||
|
||||
(defn command-request-fiat-amount-text [outgoing]
|
||||
{:font-size 12
|
||||
:color (if outgoing colors/white colors/black)})
|
||||
|
||||
(def command-request-recipient-text
|
||||
{:color colors/blue
|
||||
:font-size 14})
|
||||
|
||||
(def command-request-network-text
|
||||
{:color colors/red})
|
||||
|
||||
(def command-request-timestamp-row
|
||||
{:margin-top 6})
|
|
@ -1,177 +0,0 @@
|
|||
(ns status-im.chat.commands.input
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.chat.constants :as constants]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(defn command-ends-with-space? [text]
|
||||
(and text (string/ends-with? text constants/spacing-char)))
|
||||
|
||||
(defn starts-as-command?
|
||||
"Returns true if `text` may be treated as a command.
|
||||
To make sure that text is command we need to use `possible-chat-actions` function."
|
||||
[text]
|
||||
(and text (string/starts-with? text constants/command-char)))
|
||||
|
||||
(defn split-command-args
|
||||
"Returns a list of command's arguments including the command's name.
|
||||
|
||||
Examples:
|
||||
Input: '/send Jarrad 1.0'
|
||||
Output: ['/send' 'Jarrad' '1.0']
|
||||
|
||||
Input: '/send \"Complex name with space in between\" 1.0'
|
||||
Output: ['/send' 'Complex name with space in between' '1.0']
|
||||
|
||||
All the complex logic inside this function aims to support wrapped arguments."
|
||||
[command-text]
|
||||
(when command-text
|
||||
(let [space? (command-ends-with-space? command-text)
|
||||
command-text (if space?
|
||||
(str command-text ".")
|
||||
command-text)
|
||||
command-text-normalized (if command-text
|
||||
(string/replace (string/trim command-text) #" +" " ")
|
||||
command-text)
|
||||
splitted (cond-> (string/split command-text-normalized constants/spacing-char)
|
||||
space? (drop-last))]
|
||||
(->> splitted
|
||||
(reduce (fn [[list command-started?] arg]
|
||||
(let [quotes-count (count (filter #(= % constants/arg-wrapping-char) arg))
|
||||
has-quote? (and (= quotes-count 1)
|
||||
(string/index-of arg constants/arg-wrapping-char))
|
||||
arg (string/replace arg (re-pattern constants/arg-wrapping-char) "")
|
||||
new-list (if command-started?
|
||||
(let [index (dec (count list))]
|
||||
(update list index str constants/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
|
||||
"Transforms a list of args to a string. The opposite of `split-command-args`.
|
||||
|
||||
Examples:
|
||||
Input: ['/send' 'Jarrad' '1.0']
|
||||
Output: '/send Jarrad 1.0'
|
||||
|
||||
Input: ['/send' '\"Jarrad\"' '1.0']
|
||||
Output: '/send Jarrad 1.0'
|
||||
|
||||
Input: ['/send' 'Complex name with space in between' '1.0']
|
||||
Output: '/send \"Complex name with space in between\" 1.0'"
|
||||
[args]
|
||||
(when args
|
||||
(->> args
|
||||
(map (fn [arg]
|
||||
(let [arg (string/replace arg (re-pattern constants/arg-wrapping-char) "")]
|
||||
(if (not (string/index-of arg constants/spacing-char))
|
||||
arg
|
||||
(str constants/arg-wrapping-char arg constants/arg-wrapping-char)))))
|
||||
(string/join constants/spacing-char))))
|
||||
|
||||
(defn- current-param-position [input-text selection]
|
||||
(when selection
|
||||
(when-let [subs-input-text (subs input-text 0 selection)]
|
||||
(let [input-params (split-command-args subs-input-text)
|
||||
param-index (dec (count input-params))
|
||||
wrapping-count (get (frequencies subs-input-text) chat.constants/arg-wrapping-char 0)]
|
||||
(if (and (string/ends-with? subs-input-text chat.constants/spacing-char)
|
||||
(even? wrapping-count))
|
||||
param-index
|
||||
(dec param-index))))))
|
||||
|
||||
(defn- command-completion [input-params params]
|
||||
(let [input-params-count (count input-params)
|
||||
params-count (count params)]
|
||||
(cond
|
||||
(= input-params-count params-count) :complete
|
||||
(< input-params-count params-count) :less-then-needed
|
||||
(> input-params-count params-count) :more-than-needed)))
|
||||
|
||||
(defn selected-chat-command
|
||||
"Takes input text, text-selection and `protocol/id->command-props` map (result of
|
||||
the `chat-commands` fn) and returns the corresponding `command-props` entry,
|
||||
or nothing if input text doesn't match any available command.
|
||||
Besides keys `:params` and `:type`, the returned map contains:
|
||||
* `:input-params` - parsed parameters from the input text as map of `param-id->entered-value`
|
||||
# `:current-param-position` - index of the parameter the user is currently focused on (cursor position
|
||||
in relation to parameters), could be nil if the input is not selected
|
||||
# `:command-completion` - indication of command completion, possible values are `:complete`,
|
||||
`:less-then-needed` and `more-then-needed`"
|
||||
[input-text text-selection id->command-props]
|
||||
(when (starts-as-command? input-text)
|
||||
(let [[command-name & input-params] (split-command-args input-text)]
|
||||
(when-let [{:keys [params] :as command-props} (get id->command-props (subs command-name 1))] ;; trim leading `/` for lookup
|
||||
command-props
|
||||
(let [input-params (into {}
|
||||
(keep-indexed (fn [idx input-value]
|
||||
(when (not (string/blank? input-value))
|
||||
(when-let [param-name (get-in params [idx :id])]
|
||||
[param-name input-value]))))
|
||||
input-params)]
|
||||
(assoc command-props
|
||||
:input-params input-params
|
||||
:current-param-position (current-param-position input-text text-selection)
|
||||
:cursor-in-the-end? (= (count input-text) text-selection)
|
||||
:command-completion (command-completion input-params params)))))))
|
||||
|
||||
(defn parse-parameters
|
||||
"Parses parameters from input for defined command params,
|
||||
returns map of `param-name->param-value`"
|
||||
[params input-text]
|
||||
(let [input-params (->> (split-command-args input-text) rest (into []))]
|
||||
(into {}
|
||||
(keep-indexed (fn [idx {:keys [id]}]
|
||||
(when-let [value (get input-params idx)]
|
||||
[id value])))
|
||||
params)))
|
||||
|
||||
(fx/defn set-command-parameter
|
||||
"Set value as command parameter for the current chat"
|
||||
[{:keys [db]} last-param? param-index value]
|
||||
(let [{:keys [current-chat-id chats]} db
|
||||
[command & params] (-> (get-in chats [current-chat-id :input-text])
|
||||
split-command-args)
|
||||
param-count (count params)
|
||||
;; put the new value at the right place in parameters array
|
||||
new-params (cond-> (into [] params)
|
||||
(< param-index param-count) (assoc param-index value)
|
||||
(>= param-index param-count) (conj value))
|
||||
;; if the parameter is not the last one for the command, add space
|
||||
input-text (cond-> (str command chat.constants/spacing-char
|
||||
(join-command-args new-params))
|
||||
(and (not last-param?)
|
||||
(= param-index param-count))
|
||||
(str chat.constants/spacing-char))]
|
||||
{:db (-> db
|
||||
(chat/set-chat-ui-props {:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text] input-text))}))
|
||||
|
||||
(fx/defn select-chat-input-command
|
||||
"Takes command and (optional) map of input-parameters map and sets it as current-chat input"
|
||||
[{:keys [db]} {:keys [type params]} input-params]
|
||||
(let [{:keys [current-chat-id chat-ui-props]} db]
|
||||
{:db (-> db
|
||||
(chat/set-chat-ui-props {:show-suggestions? false
|
||||
:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text]
|
||||
(str (commands/command-name type)
|
||||
chat.constants/spacing-char
|
||||
(join-command-args input-params))))}))
|
||||
|
||||
(fx/defn set-command-reference
|
||||
"Set reference to previous command message"
|
||||
[{:keys [db] :as cofx} command-message-id]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
{:db (assoc-in db [:chats current-chat-id :metadata :responding-to-command] command-message-id)}))
|
||||
|
||||
(fx/defn clean-custom-params
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
{:db (assoc-in db [:chats current-chat-id :custom-params] nil)}))
|
|
@ -1,70 +0,0 @@
|
|||
(ns status-im.chat.commands.protocol)
|
||||
|
||||
(def or-scopes
|
||||
"Scope contexts representing OR choices"
|
||||
[#{:personal-chats :group-chats :public-chats}])
|
||||
|
||||
(defprotocol Command
|
||||
"Protocol for defining command message behaviour"
|
||||
(id [this] "Identifier of the command, used to look-up command display name as well")
|
||||
(scope [this]
|
||||
"Scope of the command, defined as set of values representing contexts
|
||||
where in which command is available, together with `id` it forms unique
|
||||
identifier for each command.
|
||||
Available values for the set are:
|
||||
`id-of-the-any-chat` - command if available only for the specified chat
|
||||
`:personal-chats` - command is available for any personal 1-1 chat
|
||||
`:group-chats` - command is available for any group chat
|
||||
`:public-chats` - command is available for any public chat ")
|
||||
(description [this] "Description of the command")
|
||||
(parameters [this]
|
||||
"Ordered sequence of command parameter templates, where each parameter
|
||||
is defined as map consisting of mandatory `:id`, `:title` and `:type` keys,
|
||||
and optional `:suggestions` field.
|
||||
When used, `:suggestions` contains reference to any generic helper component
|
||||
rendering suggestions for the argument (input code will handle when and where
|
||||
to render it)")
|
||||
(validate [this parameters cofx]
|
||||
"Function validating the parameters once command is send. Takes parameters map
|
||||
and `cofx` map as argument, returns either `nil` meaning that no errors were
|
||||
found and command send workflow can proceed, or one/more errors to display.
|
||||
Each error is represented by the map containing `:title` and `:description` keys.")
|
||||
(on-send [this command-message cofx]
|
||||
"Function which can provide any extra effects to be produced in addition to
|
||||
normal message effects which happen whenever message is sent")
|
||||
(on-receive [this command-message cofx]
|
||||
"Function which can provide any extra effects to be produced in addition to
|
||||
normal message effects which happen when particular command message is received")
|
||||
(short-preview [this command-message]
|
||||
"Function rendering the short-preview of the command message, used when
|
||||
displaying the last message in list of chats on home tab.
|
||||
There is no argument names `parameters` anymore, as the message object
|
||||
contains everything needed for short-preview/preview to render.")
|
||||
(preview [this command-message]
|
||||
"Function rendering preview of the command message in message stream"))
|
||||
|
||||
(defprotocol Yielding
|
||||
"Protocol for defining commands yielding control back to application during the send flow"
|
||||
(yield-control [this parameters cofx]
|
||||
"Function, which steps out of the normal command workflow (`validate-and-send`)
|
||||
and yields control back to application before sending.
|
||||
Useful for cases where we want to use command input handling (parameters) and/or
|
||||
validating, but we don't want to send message before yielding control elsewhere."))
|
||||
|
||||
(defprotocol EnhancedParameters
|
||||
"Protocol for command messages which wish to modify/inject additional data into parameters,
|
||||
other then those collected from the chat input.
|
||||
Good example would be the `/send` and `/request` commands - we would like to indicate
|
||||
network selected in sender's device, but we of course don't want to force user to type
|
||||
it in when it could be effortlessly looked up from context.
|
||||
Another usage would be for example command where one of the input parameters will be
|
||||
hashed after validation and we would want to avoid the original unhashed parameter
|
||||
to be ever saved on the sender device, nor to be sent over the wire.
|
||||
For maximal flexibility, parameters can be enhanced both on the sending side and receiving
|
||||
side, as sometimes thing needs to be added/enhanced in parameters map which are depending
|
||||
on the receiver context - as for example calculated fiat price values for the `/request`
|
||||
command"
|
||||
(enhance-send-parameters [this parameters cofx]
|
||||
"Function which takes original parameters + cofx map and returns new map of parameters")
|
||||
(enhance-receive-parameters [this parameters cofx]
|
||||
"Function which takes original parameters + cofx map and returns new map of parameters"))
|
|
@ -1,31 +0,0 @@
|
|||
(ns status-im.chat.commands.receiving
|
||||
(:require [status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(defn lookup-command-by-ref
|
||||
"Function which takes message object and looks up associated entry from the
|
||||
`id->command` map if it can be found"
|
||||
[{:keys [content]} id->command]
|
||||
(get id->command (:command-path content)))
|
||||
|
||||
(fx/defn receive
|
||||
"Performs receive effects for command message. Does nothing
|
||||
when message is not of the command type or command can't be found."
|
||||
[{:keys [db] :as cofx} message]
|
||||
(let [id->command (:id->command db)]
|
||||
(when-let [{:keys [type]} (lookup-command-by-ref message id->command)]
|
||||
(protocol/on-receive type (commands/enrich-command-message-for-events db message) cofx))))
|
||||
|
||||
(defn enhance-receive-parameters
|
||||
"Enhances parameters for the received command message.
|
||||
If the message is not of the command type, or command doesn't implement the
|
||||
`EnhancedParameters` protocol, returns unaltered message, otherwise updates
|
||||
its parameters."
|
||||
[{:keys [content] :as message} {:keys [db] :as cofx}]
|
||||
(let [id->command (:id->command db)
|
||||
{:keys [type]} (lookup-command-by-ref message id->command)]
|
||||
(if-let [new-params (and (satisfies? protocol/EnhancedParameters type)
|
||||
(protocol/enhance-receive-parameters type (:params content) cofx))]
|
||||
(assoc-in message [:content :params] new-params)
|
||||
message)))
|
|
@ -1,51 +0,0 @@
|
|||
(ns status-im.chat.commands.sending
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(defn- create-command-message
|
||||
"Create message map from chat-id, command & input parameters"
|
||||
[chat-id type parameter-map cofx]
|
||||
(let [command-path (commands/command-id type)
|
||||
new-parameter-map (and (satisfies? protocol/EnhancedParameters type)
|
||||
(protocol/enhance-send-parameters type parameter-map cofx))
|
||||
params (or new-parameter-map parameter-map)]
|
||||
{:chat-id chat-id
|
||||
:content-type constants/content-type-command
|
||||
:content {:chat-id chat-id
|
||||
:command-path command-path
|
||||
:params params}}))
|
||||
|
||||
(fx/defn validate-and-send
|
||||
"Validates and sends command in current chat"
|
||||
[{:keys [db] :as cofx} input-text {:keys [type params]} custom-params]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
parameter-map (merge (commands.input/parse-parameters params input-text) custom-params)]
|
||||
(if-let [validation-error (protocol/validate type parameter-map cofx)]
|
||||
;; errors during validation
|
||||
{:db (chat/set-chat-ui-props db {:validation-messages validation-error})}
|
||||
;; no errors
|
||||
(let [command-message (commands/enrich-command-message-for-events db (create-command-message chat-id type parameter-map cofx))]
|
||||
(if (satisfies? protocol/Yielding type)
|
||||
;; yield control implemented, don't send the message
|
||||
(protocol/yield-control type command-message cofx)
|
||||
;; no yield control, proceed with sending the command message
|
||||
(fx/merge cofx
|
||||
#(protocol/on-send type command-message %)
|
||||
(commands.input/set-command-reference nil)
|
||||
(commands.input/clean-custom-params)
|
||||
(chat.message/send-message command-message)))))))
|
||||
|
||||
(fx/defn send
|
||||
"Sends command with given parameters in particular chat"
|
||||
[{:keys [db] :as cofx} chat-id {:keys [type]} parameter-map]
|
||||
(let [command-message (create-command-message chat-id type parameter-map cofx)]
|
||||
(fx/merge cofx
|
||||
#(protocol/on-send type (commands/enrich-command-message-for-events db command-message) %)
|
||||
(commands.input/set-command-reference nil)
|
||||
(commands.input/clean-custom-params)
|
||||
(chat.message/send-message command-message))))
|
|
@ -1,5 +0,0 @@
|
|||
(ns status-im.chat.commands.specs
|
||||
(:require [cljs.spec.alpha :as spec]))
|
||||
|
||||
(spec/def :chat/id->command (spec/nilable map?))
|
||||
(spec/def :chat/access-scope->command-id (spec/nilable map?))
|
|
@ -1,8 +1,6 @@
|
|||
(ns status-im.chat.db
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.group-chats.db :as group-chats.db]
|
||||
|
@ -179,11 +177,3 @@
|
|||
|
||||
(def map->sorted-seq
|
||||
(comp (partial map second) (partial sort-by first)))
|
||||
|
||||
(defn available-commands
|
||||
[commands {:keys [input-text]}]
|
||||
(->> commands
|
||||
map->sorted-seq
|
||||
(filter (fn [{:keys [type]}]
|
||||
(when (commands.input/starts-as-command? input-text)
|
||||
(string/includes? (commands/command-name type) input-text))))))
|
||||
|
|
|
@ -233,8 +233,7 @@
|
|||
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(fx/merge cofx
|
||||
{:db (-> (assoc db :current-chat-id chat-id)
|
||||
(set-chat-ui-props {:validation-messages nil}))}
|
||||
{:db (assoc db :current-chat-id chat-id)}
|
||||
;; Group chat don't need this to load as all the loading of topics
|
||||
;; happens on membership changes
|
||||
(when-not (group-chat? cofx chat-id)
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
(:require [clojure.string :as string]
|
||||
[goog.object :as object]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.commands.sending :as commands.sending]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.message-content :as message-content]
|
||||
|
@ -30,8 +27,7 @@
|
|||
"Set input text for current-chat. Takes db and input text and cofx
|
||||
as arguments and returns new fx. Always clear all validation messages."
|
||||
[{{:keys [current-chat-id] :as db} :db} new-input]
|
||||
{:db (-> (chat/set-chat-ui-props db {:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text] (text->emoji new-input)))})
|
||||
{:db (assoc-in db [:chats current-chat-id :input-text] (text->emoji new-input))})
|
||||
|
||||
(defn- start-cooldown [{:keys [db]} cooldowns]
|
||||
{:dispatch-later [{:dispatch [:chat/disable-cooldown]
|
||||
|
@ -71,21 +67,6 @@
|
|||
(when-let [cmp-ref (get-in chat-ui-props [current-chat-id ref])]
|
||||
{::focus-rn-component cmp-ref}))
|
||||
|
||||
(fx/defn select-chat-input-command
|
||||
"Sets chat command and focuses on input"
|
||||
[{:keys [db] :as cofx} command params previous-command-message]
|
||||
(fx/merge cofx
|
||||
(commands.input/set-command-reference previous-command-message)
|
||||
(commands.input/select-chat-input-command command params)
|
||||
(chat-input-focus :input-ref)))
|
||||
|
||||
(fx/defn set-command-prefix
|
||||
"Sets command prefix character and focuses on input"
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(set-chat-input-text chat.constants/command-char)
|
||||
(chat-input-focus :input-ref)))
|
||||
|
||||
(fx/defn reply-to-message
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
[{:keys [db] :as cofx} message-id]
|
||||
|
@ -103,24 +84,8 @@
|
|||
{:db (assoc-in db [:chats current-chat-id :metadata :responding-to-message] nil)}
|
||||
(chat-input-focus :input-ref))))
|
||||
|
||||
(defn command-complete-fx
|
||||
"command is complete, proceed with command processing"
|
||||
[cofx input-text command custom-params]
|
||||
(fx/merge cofx
|
||||
(commands.sending/validate-and-send input-text command custom-params)
|
||||
(set-chat-input-text nil)
|
||||
(process-cooldown)))
|
||||
|
||||
(defn command-not-complete-fx
|
||||
"command is not complete, just add space after command if necessary"
|
||||
[input-text current-chat-id {:keys [db]}]
|
||||
{:db (cond-> db
|
||||
(not (commands.input/command-ends-with-space? input-text))
|
||||
(assoc-in [:chats current-chat-id :input-text]
|
||||
(str input-text chat.constants/spacing-char)))})
|
||||
|
||||
(defn plain-text-message-fx
|
||||
"no command detected, when not empty, proceed by sending text message without command processing"
|
||||
"when not empty, proceed by sending text message"
|
||||
[input-text current-chat-id {:keys [db] :as cofx}]
|
||||
(when-not (string/blank? input-text)
|
||||
(let [{:keys [message-id]}
|
||||
|
@ -141,7 +106,6 @@
|
|||
(assoc :response-to message-id)
|
||||
preferred-name
|
||||
(assoc :name preferred-name))})
|
||||
(commands.input/set-command-reference nil)
|
||||
(set-chat-input-text nil)
|
||||
(process-cooldown)))))
|
||||
|
||||
|
@ -157,23 +121,16 @@
|
|||
|
||||
(fx/defn send-current-message
|
||||
"Sends message from current chat input"
|
||||
[{{:keys [current-chat-id id->command access-scope->command-id] :as db} :db :as cofx}]
|
||||
(let [{:keys [input-text custom-params]} (get-in db [:chats current-chat-id])
|
||||
command (commands.input/selected-chat-command
|
||||
input-text nil (commands/chat-commands id->command
|
||||
access-scope->command-id
|
||||
(get-in db [:chats current-chat-id])))]
|
||||
(if command
|
||||
;; Returns true if current input contains command
|
||||
(if (= :complete (:command-completion command))
|
||||
(command-complete-fx cofx input-text command custom-params)
|
||||
(command-not-complete-fx input-text current-chat-id cofx))
|
||||
(plain-text-message-fx input-text current-chat-id cofx))))
|
||||
[{{:keys [current-chat-id] :as db} :db :as cofx}]
|
||||
(let [{:keys [input-text]} (get-in db [:chats current-chat-id])]
|
||||
(plain-text-message-fx input-text current-chat-id cofx)))
|
||||
|
||||
(fx/defn send-transaction-result
|
||||
{:events [:chat/send-transaction-result]}
|
||||
[cofx chat-id params result]
|
||||
(commands.sending/send cofx chat-id (get-in cofx [:db :id->command ["send" #{:personal-chats}]]) (assoc params :tx-hash result)))
|
||||
;;TODO: should be implemented on status-go side
|
||||
;;see https://github.com/status-im/team-core/blob/6c3d67d8e8bd8500abe52dab06a59e976ec942d2/rfc-001.md#status-gostatus-react-interface
|
||||
)
|
||||
|
||||
;; effects
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.transport.filters.core :as filters]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
|
@ -30,8 +29,7 @@
|
|||
(fx/merge cofx
|
||||
{:db (assoc db :chats chats
|
||||
:chats/loading? false)}
|
||||
(filters/load-filters)
|
||||
(commands/load-commands commands/register))))
|
||||
(filters/load-filters))))
|
||||
|
||||
(fx/defn initialize-chats
|
||||
"Initialize persisted chats on startup"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
(ns status-im.chat.models.message
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.chat.models :as chat-model]
|
||||
|
@ -120,20 +119,16 @@
|
|||
|
||||
(fx/defn add-received-message
|
||||
[{:keys [db] :as cofx}
|
||||
{:keys [from message-id chat-id content metadata] :as raw-message}]
|
||||
{:keys [from message-id chat-id content metadata] :as message}]
|
||||
(let [{:keys [current-chat-id view-id]} db
|
||||
current-public-key (multiaccounts.model/current-public-key cofx)
|
||||
current-chat? (and (or (= :chat view-id)
|
||||
(= :chat-modal view-id))
|
||||
(= current-chat-id chat-id))
|
||||
message (-> raw-message
|
||||
(commands-receiving/enhance-receive-parameters cofx))]
|
||||
(fx/merge cofx
|
||||
(add-message {:batch? true
|
||||
:message message
|
||||
:metadata metadata
|
||||
:current-chat? current-chat?})
|
||||
(commands-receiving/receive message))))
|
||||
(= current-chat-id chat-id))]
|
||||
(add-message cofx {:batch? true
|
||||
:message message
|
||||
:metadata metadata
|
||||
:current-chat? current-chat?})))
|
||||
|
||||
(defn- add-to-chat?
|
||||
[{:keys [db]} {:keys [chat-id clock-value message-id from]}]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.chat.specs
|
||||
(:require [cljs.spec.alpha :as s]
|
||||
status-im.chat.commands.specs))
|
||||
(:require [cljs.spec.alpha :as s]))
|
||||
|
||||
(s/def :chat/chats (s/nilable map?)) ; {id (string) chat (map)} active chats on chat's tab
|
||||
(s/def :chat/current-chat-id (s/nilable string?)) ; current or last opened chat-id
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
(def content-type-text "text/plain")
|
||||
(def content-type-sticker "sticker")
|
||||
(def content-type-status "status")
|
||||
(def content-type-command "command")
|
||||
(def content-type-command-request "command-request")
|
||||
(def content-type-emoji "emoji")
|
||||
|
||||
(def desktop-content-types
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
[status-im.bootnodes.core :as bootnodes]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.input :as chat.input]
|
||||
|
@ -66,7 +64,6 @@
|
|||
[status-im.wallet.custom-tokens.core :as custom-tokens]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.commands.sending :as commands.sending]
|
||||
[status-im.utils.money :as money]
|
||||
status-im.popover.core))
|
||||
|
||||
|
@ -572,16 +569,6 @@
|
|||
(fn [cofx [_ text]]
|
||||
(chat.input/set-chat-input-text cofx text)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/select-chat-input-command
|
||||
(fn [cofx [_ command params previous-command-message]]
|
||||
(chat.input/select-chat-input-command cofx command params previous-command-message)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/set-command-prefix
|
||||
(fn [cofx _]
|
||||
(chat.input/set-command-prefix cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/cancel-message-reply
|
||||
(fn [cofx _]
|
||||
|
@ -597,20 +584,6 @@
|
|||
(fn [cofx _]
|
||||
(chat.input/send-current-message cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/set-command-parameter
|
||||
(fn [{{:keys [chats current-chat-id chat-ui-props id->command access-scope->command-id]} :db :as cofx} [_ value]]
|
||||
(let [current-chat (get chats current-chat-id)
|
||||
selection (get-in chat-ui-props [current-chat-id :selection])
|
||||
commands (commands/chat-commands id->command access-scope->command-id current-chat)
|
||||
{:keys [current-param-position params]} (commands.input/selected-chat-command
|
||||
(:input-text current-chat) selection commands)
|
||||
last-param-idx (dec (count params))]
|
||||
(commands.input/set-command-parameter cofx
|
||||
(= current-param-position last-param-idx)
|
||||
current-param-position
|
||||
value))))
|
||||
|
||||
(defn- mark-messages-seen
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [current-chat-id]} db]
|
||||
|
@ -1589,7 +1562,8 @@
|
|||
(fx/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(chat/start-chat public-key nil)
|
||||
(commands.sending/send public-key
|
||||
request-command
|
||||
{:asset (name symbol)
|
||||
:amount (str (money/internal->formatted amount symbol decimals))})))))
|
||||
;; TODO send
|
||||
#_(commands.sending/send public-key
|
||||
request-command
|
||||
{:asset (name symbol)
|
||||
:amount (str (money/internal->formatted amount symbol decimals))})))))
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
[taoensso.timbre :as log]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.chat.models :as chat.models]
|
||||
|
@ -119,9 +117,7 @@
|
|||
;;chat
|
||||
(reg-root-key-sub ::cooldown-enabled? :chat/cooldown-enabled?)
|
||||
(reg-root-key-sub ::chats :chats)
|
||||
(reg-root-key-sub ::access-scope->command-id :access-scope->command-id)
|
||||
(reg-root-key-sub ::chat-ui-props :chat-ui-props)
|
||||
(reg-root-key-sub :chats/id->command :id->command)
|
||||
(reg-root-key-sub :chats/current-chat-id :current-chat-id)
|
||||
(reg-root-key-sub :public-group-topic :public-group-topic)
|
||||
(reg-root-key-sub :chats/loading? :chats/loading?)
|
||||
|
@ -523,31 +519,6 @@
|
|||
(fn [collectibles [_ {:keys [symbol token]}]]
|
||||
(get-in collectibles [(keyword symbol) (js/parseInt token)])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::show-suggestions-view?
|
||||
:<- [:chats/current-chat-ui-prop :show-suggestions?]
|
||||
:<- [:chats/current-chat-input-text]
|
||||
:<- [:chats/all-available-commands]
|
||||
(fn [[show-suggestions? input-text commands]]
|
||||
(and (or show-suggestions?
|
||||
(commands.input/starts-as-command? (string/trim (or input-text ""))))
|
||||
(seq commands))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::show-suggestions?
|
||||
:<- [::show-suggestions-view?]
|
||||
:<- [:chats/selected-chat-command]
|
||||
(fn [[show-suggestions-box? selected-command]]
|
||||
(and show-suggestions-box? (not selected-command))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::get-commands-for-chat
|
||||
:<- [:chats/id->command]
|
||||
:<- [::access-scope->command-id]
|
||||
:<- [:chats/current-raw-chat]
|
||||
(fn [[id->command access-scope->command-id chat]]
|
||||
(commands/chat-commands id->command access-scope->command-id chat)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/chat
|
||||
:<- [:chats/active-chats]
|
||||
|
@ -593,12 +564,6 @@
|
|||
(fn [ui-props [_ prop]]
|
||||
(get ui-props prop)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/validation-messages
|
||||
:<- [:chats/current-chat-ui-props]
|
||||
(fn [ui-props]
|
||||
(some-> ui-props :validation-messages)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/input-margin
|
||||
:<- [:keyboard-height]
|
||||
|
@ -817,55 +782,6 @@
|
|||
:empty
|
||||
:messages))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/available-commands
|
||||
:<- [::get-commands-for-chat]
|
||||
:<- [:chats/current-chat]
|
||||
(fn [[commands chat]]
|
||||
(chat.db/available-commands commands chat)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/all-available-commands
|
||||
:<- [::get-commands-for-chat]
|
||||
(fn [commands]
|
||||
(chat.db/map->sorted-seq commands)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/selected-chat-command
|
||||
:<- [:chats/current-chat-input-text]
|
||||
:<- [:chats/current-chat-ui-prop :selection]
|
||||
:<- [::get-commands-for-chat]
|
||||
(fn [[input-text selection commands]]
|
||||
(commands.input/selected-chat-command input-text selection commands)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/input-placeholder
|
||||
:<- [:chats/current-chat]
|
||||
:<- [:chats/selected-chat-command]
|
||||
(fn [[{:keys [input-text]} {:keys [params current-param-position cursor-in-the-end?]}]]
|
||||
(when (and cursor-in-the-end? (string/ends-with? (or input-text "") chat.constants/spacing-char))
|
||||
(get-in params [current-param-position :placeholder]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/parameter-box
|
||||
:<- [:chats/current-chat]
|
||||
:<- [:chats/selected-chat-command]
|
||||
(fn [[_ {:keys [current-param-position params]}]]
|
||||
(when (and params current-param-position)
|
||||
(get-in params [current-param-position :suggestions]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/show-parameter-box?
|
||||
:<- [:chats/parameter-box]
|
||||
:<- [::show-suggestions?]
|
||||
:<- [:chats/validation-messages]
|
||||
:<- [:chats/selected-chat-command]
|
||||
(fn [[chat-parameter-box show-suggestions? validation-messages {:keys [command-completion]}]]
|
||||
(and chat-parameter-box
|
||||
(not validation-messages)
|
||||
(not show-suggestions?)
|
||||
(not (= :complete command-completion)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/unviewed-messages-count
|
||||
(fn [[_ chat-id]]
|
||||
|
|
|
@ -53,14 +53,13 @@
|
|||
|
||||
(spec/def :message.content/text (spec/and string? (complement s/blank?)))
|
||||
(spec/def :message.content/response-to string?)
|
||||
(spec/def :message.content/command-path (spec/tuple string? (spec/coll-of (spec/or :scope keyword? :chat-id string?) :kind set? :min-count 1)))
|
||||
(spec/def :message.content/uri (spec/and string? (complement s/blank?)))
|
||||
(spec/def :message.content/pack (spec/and string? (complement s/blank?)))
|
||||
(spec/def :message.content/params (spec/map-of keyword? any?))
|
||||
|
||||
(spec/def ::content-type #{constants/content-type-text constants/content-type-command
|
||||
(spec/def ::content-type #{constants/content-type-text
|
||||
constants/content-type-emoji
|
||||
constants/content-type-command-request constants/content-type-sticker})
|
||||
constants/content-type-sticker})
|
||||
(spec/def ::message-type #{:group-user-message :public-group-user-message :user-message})
|
||||
(spec/def ::clock-value (spec/and pos-int?
|
||||
utils.clocks/safe-timestamp?))
|
||||
|
@ -91,20 +90,11 @@
|
|||
(spec/def :message/message-common (spec/keys :req-un [::content-type ::message-type ::clock-value ::timestamp]))
|
||||
(spec/def :message.text/content (spec/keys :req-un [:message.content/text]
|
||||
:req-opt [:message.content/response-to]))
|
||||
(spec/def :message.command/content (spec/keys :req-un [:message.content/command-path :message.content/params]))
|
||||
|
||||
(spec/def :message.sticker/content (spec/keys :req-un [:message.content/hash]))
|
||||
|
||||
(defmulti content-type :content-type)
|
||||
|
||||
(defmethod content-type constants/content-type-command [_]
|
||||
(spec/merge :message/message-common
|
||||
(spec/keys :req-un [:message.command/content])))
|
||||
|
||||
(defmethod content-type constants/content-type-command-request [_]
|
||||
(spec/merge :message/message-common
|
||||
(spec/keys :req-un [:message.command/content])))
|
||||
|
||||
(defmethod content-type constants/content-type-sticker [_]
|
||||
(spec/merge :message/message-common
|
||||
(spec/keys :req-un [:message.sticker/content])))
|
||||
|
|
|
@ -40,24 +40,6 @@
|
|||
(rep [this {:keys [name profile-image address]}]
|
||||
#js [name profile-image address nil nil]))
|
||||
|
||||
;; It's necessary to support old clients understanding only older, verbose command content (`release/0.9.25` and older)
|
||||
(defn- new->legacy-command-data [{:keys [command-path params] :as content}]
|
||||
(get {["send" #{:personal-chats}] [{:command-ref ["transactor" :command 83 "send"]
|
||||
:command "send"
|
||||
:bot "transactor"
|
||||
:command-scope-bitmask 83}
|
||||
constants/content-type-command]
|
||||
["request" #{:personal-chats}] [{:command-ref ["transactor" :command 83 "request"]
|
||||
:request-command-ref ["transactor" :command 83 "send"]
|
||||
:command "request"
|
||||
:request-command "send"
|
||||
:bot "transactor"
|
||||
:command-scope-bitmask 83
|
||||
:prefill [(get params :asset)
|
||||
(get params :amount)]}
|
||||
constants/content-type-command-request]}
|
||||
command-path))
|
||||
|
||||
(deftype MessageHandler []
|
||||
Object
|
||||
(tag [this v] "c4")
|
||||
|
@ -65,9 +47,6 @@
|
|||
(condp = content-type
|
||||
constants/content-type-text ;; append new content add the end, still pass content the old way at the old index
|
||||
#js [(:text content) content-type message-type clock-value timestamp content]
|
||||
constants/content-type-command ;; handle command compatibility issues
|
||||
(let [[legacy-content legacy-content-type] (new->legacy-command-data content)]
|
||||
#js [(merge content legacy-content) (or legacy-content-type content-type) message-type clock-value timestamp])
|
||||
;; no need for legacy conversions for rest of the content types
|
||||
#js [content content-type message-type clock-value timestamp])))
|
||||
|
||||
|
@ -103,17 +82,6 @@
|
|||
;; Reader handlers
|
||||
;;
|
||||
|
||||
(def ^:private legacy-ref->new-path
|
||||
{["transactor" :command 83 "send"] ["send" #{:personal-chats}]
|
||||
["transactor" :command 83 "request"] ["request" #{:personal-chats}]})
|
||||
|
||||
(defn- legacy->new-command-content [{:keys [command-path command-ref] :as content}]
|
||||
(if command-path
|
||||
;; `:command-path` set, message produced by newer app version, nothing to do
|
||||
content
|
||||
;; we have to look up `:command-path` based on legacy `:command-ref` value (`release/0.9.25` and older) and assoc it to content
|
||||
(assoc content :command-path (get legacy-ref->new-path command-ref))))
|
||||
|
||||
(defn- legacy->new-message-data [content content-type]
|
||||
;; handling only the text content case
|
||||
(cond
|
||||
|
@ -123,9 +91,6 @@
|
|||
[content content-type]
|
||||
;; create safe `{:text string-content}` value from anything else
|
||||
[{:text (str content)} content-type])
|
||||
(or (= content-type constants/content-type-command)
|
||||
(= content-type constants/content-type-command-request))
|
||||
[(legacy->new-command-content content) constants/content-type-command]
|
||||
:else
|
||||
[content content-type]))
|
||||
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.chat.styles.input.input :as style]
|
||||
[status-im.ui.screens.chat.styles.message.message :as message-style]
|
||||
[status-im.ui.screens.chat.input.parameter-box :as parameter-box]
|
||||
[status-im.ui.screens.chat.input.send-button :as send-button]
|
||||
[status-im.ui.screens.chat.input.suggestions :as suggestions]
|
||||
[status-im.ui.screens.chat.input.validation-messages :as validation-messages]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.chat.utils :as chat-utils]
|
||||
[status-im.i18n :as i18n]
|
||||
|
@ -100,24 +97,6 @@
|
|||
(set-layout-width-fn w))}
|
||||
(or input-text "")]))
|
||||
|
||||
(defn- input-helper-view-on-update [{:keys [opacity-value placeholder]}]
|
||||
(fn [_]
|
||||
(let [to-value (if @placeholder 1 0)]
|
||||
(animation/start
|
||||
(animation/timing opacity-value {:toValue to-value
|
||||
:duration 300
|
||||
:useNativeDriver true})))))
|
||||
|
||||
(defview input-helper [{:keys [width]}]
|
||||
(letsubs [placeholder [:chats/input-placeholder]
|
||||
opacity-value (animation/create-value 0)
|
||||
on-update (input-helper-view-on-update {:opacity-value opacity-value
|
||||
:placeholder placeholder})]
|
||||
{:component-did-update on-update}
|
||||
[react/animated-view {:style (style/input-helper-view width opacity-value)}
|
||||
[react/text {:style (style/input-helper-text width)}
|
||||
placeholder]]))
|
||||
|
||||
(defn get-options [type]
|
||||
(case (keyword type)
|
||||
:phone {:keyboard-type "phone-pad"}
|
||||
|
@ -126,33 +105,20 @@
|
|||
nil))
|
||||
|
||||
(defview input-view [{:keys [single-line-input? set-text state-text]}]
|
||||
(letsubs [command [:chats/selected-chat-command]]
|
||||
(let [component (reagent/current-component)
|
||||
set-layout-width-fn #(reagent/set-state component {:width %})
|
||||
set-container-width-fn #(reagent/set-state component {:container-width %})
|
||||
{:keys [width]} (reagent/state component)]
|
||||
[react/view {:style style/input-root}
|
||||
[react/animated-view {:style style/input-animated}
|
||||
[invisible-input {:set-layout-width-fn set-layout-width-fn}]
|
||||
(if platform/desktop?
|
||||
[basic-text-input-desktop {:set-container-width-fn set-container-width-fn
|
||||
:single-line-input? single-line-input?
|
||||
:set-text set-text
|
||||
:state-text state-text}]
|
||||
[basic-text-input {:set-container-width-fn set-container-width-fn
|
||||
:single-line-input? single-line-input?}])
|
||||
[input-helper {:width width}]]])))
|
||||
|
||||
(defview commands-button []
|
||||
(letsubs [commands [:chats/all-available-commands]
|
||||
reply-message [:chats/reply-message]]
|
||||
(when (and (not reply-message) (seq commands))
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/set-command-prefix])
|
||||
:accessibility-label :chat-commands-button}
|
||||
[react/view
|
||||
[vector-icons/icon :main-icons/commands {:container-style style/input-commands-icon
|
||||
:color colors/gray}]]])))
|
||||
(let [component (reagent/current-component)
|
||||
set-layout-width-fn #(reagent/set-state component {:width %})
|
||||
set-container-width-fn #(reagent/set-state component {:container-width %})
|
||||
{:keys [width]} (reagent/state component)]
|
||||
[react/view {:style style/input-root}
|
||||
[react/animated-view {:style style/input-animated}
|
||||
[invisible-input {:set-layout-width-fn set-layout-width-fn}]
|
||||
(if platform/desktop?
|
||||
[basic-text-input-desktop {:set-container-width-fn set-container-width-fn
|
||||
:single-line-input? single-line-input?
|
||||
:set-text set-text
|
||||
:state-text state-text}]
|
||||
[basic-text-input {:set-container-width-fn set-container-width-fn
|
||||
:single-line-input? single-line-input?}])]]))
|
||||
|
||||
(defview reply-message [from alias message-text]
|
||||
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]
|
||||
|
@ -183,7 +149,7 @@
|
|||
:height 19
|
||||
:color colors/white}]]]]])))
|
||||
|
||||
(defview input-container []
|
||||
(defview container []
|
||||
(letsubs [margin [:chats/input-margin]
|
||||
mainnet? [:mainnet?]
|
||||
input-text [:chats/current-chat-input-text]
|
||||
|
@ -221,10 +187,3 @@
|
|||
(set-text ""))]
|
||||
[send-button/send-button-view {:input-text input-text}
|
||||
#(re-frame/dispatch [:chat.ui/send-current-message])]))]])))
|
||||
|
||||
(defn container []
|
||||
[react/view
|
||||
[parameter-box/parameter-box-view]
|
||||
[suggestions/suggestions-view]
|
||||
[validation-messages/validation-messages-view]
|
||||
[input-container]])
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.input.parameter-box
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.ui.screens.chat.input.animations.expandable :as expandable]
|
||||
[status-im.ui.screens.chat.styles.input.parameter-box :as style]
|
||||
[status-im.ui.components.react :as react]))
|
||||
|
||||
(defview parameter-box-container []
|
||||
(letsubs [parameter-box [:chats/parameter-box]]
|
||||
(when parameter-box
|
||||
[react/view
|
||||
[parameter-box]])))
|
||||
|
||||
(defview parameter-box-view []
|
||||
(letsubs [show-box? [:chats/show-parameter-box?]]
|
||||
(when show-box?
|
||||
[expandable/expandable-view {:key :parameter-box}
|
||||
;; TODO need to add the whole payload (and details about previous parameters?)
|
||||
[parameter-box-container]])))
|
|
@ -9,17 +9,13 @@
|
|||
(defn sendable? [input-text disconnected? login-processing?]
|
||||
(let [trimmed (string/trim input-text)]
|
||||
(not (or (string/blank? trimmed)
|
||||
(= trimmed "/")
|
||||
login-processing?
|
||||
disconnected?))))
|
||||
|
||||
(defview send-button-view [{:keys [input-text]} on-send-press]
|
||||
(letsubs [{:keys [command-completion]} [:chats/selected-chat-command]
|
||||
disconnected? [:disconnected?]
|
||||
(letsubs [disconnected? [:disconnected?]
|
||||
{:keys [processing]} [:multiaccounts/login]]
|
||||
(when (and (sendable? input-text disconnected? processing)
|
||||
(or (not command-completion)
|
||||
(#{:complete :less-than-needed} command-completion)))
|
||||
(when (sendable? input-text disconnected? processing)
|
||||
[react/touchable-highlight
|
||||
{:on-press on-send-press}
|
||||
[vector-icons/icon :main-icons/arrow-up
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.input.suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.chat.styles.input.suggestions :as style]
|
||||
[status-im.ui.screens.chat.input.animations.expandable :as expandable]
|
||||
[status-im.chat.commands.core :as commands]))
|
||||
|
||||
(defn suggestion-item [{:keys [on-press name description last? accessibility-label]}]
|
||||
[react/touchable-highlight (cond-> {:on-press on-press}
|
||||
accessibility-label (assoc :accessibility-label accessibility-label))
|
||||
[react/view style/item-suggestion-container
|
||||
[react/text name]
|
||||
[react/text {:style style/item-suggestion-description
|
||||
:number-of-lines 2}
|
||||
description]]])
|
||||
|
||||
(defview suggestions-view []
|
||||
(letsubs [available-commands [:chats/available-commands]]
|
||||
(when (seq available-commands)
|
||||
[expandable/expandable-view {:key :suggestions}
|
||||
[react/view
|
||||
[react/scroll-view {:keyboard-should-persist-taps :always
|
||||
:bounces false}
|
||||
(map-indexed
|
||||
(fn [i {:keys [type] :as command}]
|
||||
^{:key i}
|
||||
[suggestion-item {:on-press #(re-frame/dispatch [:chat.ui/select-chat-input-command command nil])
|
||||
:name (commands/command-name type)
|
||||
:description (commands/command-description type)
|
||||
:last? (= i (dec (count available-commands)))
|
||||
:accessibility-label (commands/accessibility-label type)}])
|
||||
available-commands)]]])))
|
|
@ -1,29 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.input.validation-messages
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.chat.styles.input.validation-message :as style]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(defn validation-message [{:keys [title description]}]
|
||||
[react/view style/message-container
|
||||
[react/text {:style style/message-title}
|
||||
title]
|
||||
[react/text {:style style/message-description}
|
||||
description]])
|
||||
|
||||
(defn- messages-list [markup]
|
||||
[react/view {:flex 1}
|
||||
markup])
|
||||
|
||||
(defview validation-messages-view []
|
||||
(letsubs [chat-input-margin [:chats/input-margin]
|
||||
input-height [:chats/current-chat-ui-prop :input-height]
|
||||
validation-result [:chats/validation-messages]]
|
||||
(when validation-result
|
||||
(let [message (if (string? validation-result)
|
||||
{:title (i18n/label :t/error)
|
||||
:description validation-result}
|
||||
validation-result)]
|
||||
[react/view (style/root (+ input-height chat-input-margin))
|
||||
[messages-list [validation-message message]]]))))
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.ui.screens.chat.message.message
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.i18n :as i18n]
|
||||
|
@ -19,41 +18,35 @@
|
|||
[status-im.utils.platform :as platform])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defview message-content-command
|
||||
[command-message]
|
||||
(letsubs [id->command [:chats/id->command]
|
||||
{:keys [contacts]} [:chats/current-chat]]
|
||||
(let [{:keys [type] :as command} (commands-receiving/lookup-command-by-ref command-message id->command)]
|
||||
;;TODO temporary disable commands for v1
|
||||
[react/text (str "Unhandled command: " (-> command-message :content :command-path first))])))
|
||||
|
||||
(defview message-timestamp
|
||||
[t justify-timestamp? outgoing command? content content-type]
|
||||
(when-not command?
|
||||
[react/text {:style (style/message-timestamp-text
|
||||
justify-timestamp?
|
||||
outgoing
|
||||
(:rtl? content)
|
||||
(= content-type constants/content-type-emoji))} t]))
|
||||
(defn message-timestamp
|
||||
[t justify-timestamp? outgoing content content-type]
|
||||
[react/text {:style (style/message-timestamp-text
|
||||
justify-timestamp?
|
||||
outgoing
|
||||
(:rtl? content)
|
||||
(= content-type constants/content-type-emoji))} t])
|
||||
|
||||
(defn message-view
|
||||
[{:keys [timestamp-str outgoing content content-type] :as message} message-content {:keys [justify-timestamp?]}]
|
||||
[{:keys [timestamp-str outgoing content content-type] :as message}
|
||||
message-content {:keys [justify-timestamp?]}]
|
||||
[react/view (style/message-view message)
|
||||
message-content
|
||||
[message-timestamp timestamp-str justify-timestamp? outgoing (or (get content :command-path)
|
||||
(get content :command-ref))
|
||||
[message-timestamp timestamp-str justify-timestamp? outgoing
|
||||
content content-type]])
|
||||
|
||||
(defview quoted-message [message-id {:keys [from text]} outgoing current-public-key]
|
||||
(letsubs [{:keys [quote
|
||||
ens-name
|
||||
alias]}
|
||||
(defview quoted-message
|
||||
[message-id {:keys [from text]} outgoing current-public-key]
|
||||
(letsubs [{:keys [quote ens-name alias]}
|
||||
[:messages/quote-info message-id]]
|
||||
(when (or quote text)
|
||||
[react/view {:style (style/quoted-message-container outgoing)}
|
||||
[react/view {:style style/quoted-message-author-container}
|
||||
[vector-icons/tiny-icon :tiny-icons/tiny-reply {:color (if outgoing colors/white-transparent colors/gray)}]
|
||||
(chat.utils/format-reply-author (or from (:from quote)) alias ens-name current-public-key (partial style/quoted-message-author outgoing))]
|
||||
[vector-icons/tiny-icon :tiny-icons/tiny-reply
|
||||
{:color (if outgoing colors/white-transparent colors/gray)}]
|
||||
(chat.utils/format-reply-author
|
||||
(or from (:from quote))
|
||||
alias ens-name current-public-key
|
||||
(partial style/quoted-message-author outgoing))]
|
||||
|
||||
[react/text {:style (style/quoted-message-text outgoing)
|
||||
:number-of-lines 5}
|
||||
|
@ -183,17 +176,6 @@
|
|||
[wrapper message]
|
||||
[wrapper message [message-content-status message]])
|
||||
|
||||
(defmethod message-content constants/content-type-command
|
||||
[wrapper message]
|
||||
[wrapper message
|
||||
[message-view message [message-content-command message]]])
|
||||
|
||||
;; Todo remove after couple of releases
|
||||
(defmethod message-content constants/content-type-command-request
|
||||
[wrapper message]
|
||||
[wrapper message
|
||||
[message-view message [message-content-command message]]])
|
||||
|
||||
(defmethod message-content constants/content-type-emoji
|
||||
[wrapper message]
|
||||
[wrapper message [emoji-message message]])
|
||||
|
@ -234,15 +216,6 @@
|
|||
[react/view style/not-sent-icon
|
||||
[vector-icons/icon :main-icons/warning {:color colors/red}]]]])
|
||||
|
||||
(defview command-status [{{:keys [network]} :params}]
|
||||
(letsubs [current-network [:chain-name]]
|
||||
(when (and network (not= current-network network))
|
||||
[react/view style/not-sent-view
|
||||
[react/text {:style style/not-sent-text}
|
||||
(i18n/label :network-mismatch)]
|
||||
[react/view style/not-sent-icon
|
||||
[vector-icons/icon :main-icons/warning {:color colors/red}]]])))
|
||||
|
||||
(defn message-delivery-status
|
||||
[{:keys [chat-id message-id outgoing-status
|
||||
first-outgoing?
|
||||
|
@ -255,9 +228,7 @@
|
|||
[react/view style/delivery-view
|
||||
[react/text {:style style/delivery-text}
|
||||
(i18n/label :t/status-sent)]])
|
||||
(when (and (not outgoing-status)
|
||||
(:command content))
|
||||
[command-status content]))))
|
||||
nil)))
|
||||
|
||||
(defview message-author-name [from alias]
|
||||
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]]
|
||||
|
|
|
@ -152,26 +152,8 @@
|
|||
:height min-input-height
|
||||
:left left}})
|
||||
|
||||
(def input-commands-icon
|
||||
{:margin 14
|
||||
:height 24
|
||||
:width 24})
|
||||
|
||||
(def input-clear-container
|
||||
{:width 24
|
||||
:height 24
|
||||
:margin-top 7
|
||||
:align-items :center})
|
||||
|
||||
(def commands-root
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def command-list-icon-container
|
||||
{:width 32
|
||||
:height 32
|
||||
:padding 4})
|
||||
|
||||
(def commands-list-icon
|
||||
{:height 24
|
||||
:width 24})
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.styles.input.parameter-box
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def root
|
||||
{:background-color colors/white
|
||||
:border-bottom-color colors/black-transparent
|
||||
:border-bottom-width 1})
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.styles.input.suggestions
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def item-height 52)
|
||||
(def border-height 1)
|
||||
|
||||
(def root
|
||||
{:background-color colors/white
|
||||
:border-top-color colors/black-transparent
|
||||
:border-top-width 1})
|
||||
|
||||
(def item-suggestion-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height item-height
|
||||
:padding-horizontal 14
|
||||
:border-top-color colors/black-transparent
|
||||
:border-top-width border-height})
|
||||
|
||||
(def item-suggestion-description
|
||||
{:flex 1
|
||||
:margin-left 10
|
||||
:color colors/gray})
|
|
@ -1,23 +0,0 @@
|
|||
(ns status-im.ui.screens.chat.styles.input.validation-message
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn root [bottom]
|
||||
{:flex-direction :column
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom bottom
|
||||
:position :absolute})
|
||||
|
||||
(def message-container
|
||||
{:background-color colors/red
|
||||
:padding 16})
|
||||
|
||||
(def message-title
|
||||
{:color colors/white
|
||||
:font-size 12})
|
||||
|
||||
(def message-description
|
||||
{:color colors/white
|
||||
:font-size 12
|
||||
:opacity 0.9})
|
|
@ -152,10 +152,7 @@
|
|||
4)}
|
||||
(if (= content-type constants/content-type-emoji)
|
||||
{:flex-direction :row}
|
||||
{:background-color (if outgoing colors/blue colors/blue-light)})
|
||||
(when (= content-type constants/content-type-command)
|
||||
{:padding-top 12
|
||||
:padding-bottom 10})))
|
||||
{:background-color (if outgoing colors/blue colors/blue-light)})))
|
||||
|
||||
(def play-image
|
||||
{:width 33
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
[status-im.utils.fx :as fx]
|
||||
[status-im.wallet.core :as wallet]))
|
||||
|
||||
(defn get-currency [db]
|
||||
(or (get-in db [:multiaccount :settings :wallet :currency]) :usd))
|
||||
|
||||
(fx/defn set-currency
|
||||
[{:keys [db] :as cofx} currency]
|
||||
(let [settings (get-in db [:multiaccount :settings])
|
||||
|
|
|
@ -193,7 +193,6 @@
|
|||
:contacts/click-action
|
||||
:contacts/click-params
|
||||
:pairing/installations
|
||||
:commands/stored-command
|
||||
:group/selected-contacts
|
||||
:multiaccounts/multiaccounts
|
||||
:multiaccounts/recover
|
||||
|
@ -303,8 +302,6 @@
|
|||
:chat/last-clock-value
|
||||
:chat/loaded-chats
|
||||
:chat/bot-db
|
||||
:chat/id->command
|
||||
:chat/access-scope->command-id
|
||||
:ens/registration
|
||||
:wallet/wallet
|
||||
:prices/prices
|
||||
|
|
|
@ -27,16 +27,6 @@
|
|||
:margin-right 16
|
||||
:width 60})
|
||||
|
||||
(def message-command-container
|
||||
{:align-self :flex-start
|
||||
:border-radius 8
|
||||
:border-color colors/black-transparent
|
||||
:border-width 1
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 10
|
||||
:align-items :flex-start
|
||||
:width 230})
|
||||
|
||||
(def author
|
||||
{:font-weight "500"
|
||||
:font-size 14})
|
||||
|
|
|
@ -161,17 +161,6 @@
|
|||
|
||||
(defmulti message (fn [_ _ {:keys [content-type]}] content-type))
|
||||
|
||||
(defmethod message constants/content-type-command
|
||||
[_ _ {:keys [from] :as message}]
|
||||
[react/view
|
||||
[react/view {:style {:flex-direction :row :align-items :center :margin-top 15}}
|
||||
[member-photo from]
|
||||
[message-author-name message]]
|
||||
[react/view {:style styles/not-first-in-group-wrapper}
|
||||
[photo-placeholder]
|
||||
[react/view {:style styles/message-command-container}
|
||||
[message/message-content-command message]]]])
|
||||
|
||||
(defmethod message constants/content-type-sticker
|
||||
[_ _ {:keys [content] :as message}]
|
||||
[message-wrapper message
|
||||
|
|
|
@ -60,10 +60,8 @@
|
|||
[react/text {:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style styles/chat-last-message}
|
||||
(if (= constants/content-type-command (:content-type last-message))
|
||||
[chat-item/command-short-preview last-message]
|
||||
(or (:text last-message-content)
|
||||
(i18n/label :no-messages-yet)))]))]
|
||||
(or (:text last-message-content)
|
||||
(i18n/label :no-messages-yet))]))]
|
||||
[react/view {:style styles/timestamp}
|
||||
[chat-item/message-timestamp (:timestamp last-message)]
|
||||
(when (pos? unviewed-messages-count)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
(ns status-im.ui.screens.home.views.inner-item
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
|
@ -16,12 +14,6 @@
|
|||
[status-im.utils.datetime :as time])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defview command-short-preview [message]
|
||||
(letsubs [id->command [:chats/id->command]
|
||||
{:keys [contacts]} [:chats/current-chat]]
|
||||
(when-let [command (commands-receiving/lookup-command-by-ref message id->command)]
|
||||
(commands/generate-short-preview command (commands/add-chat-contacts contacts message)))))
|
||||
|
||||
(defn message-content-text [{:keys [content content-type] :as message}]
|
||||
[react/view styles/last-message-container
|
||||
(cond
|
||||
|
@ -31,9 +23,6 @@
|
|||
:accessibility-label :no-messages-text}
|
||||
(i18n/label :t/no-messages)]
|
||||
|
||||
(= constants/content-type-command content-type)
|
||||
[command-short-preview message]
|
||||
|
||||
(= constants/content-type-sticker content-type)
|
||||
[react/image {:style {:margin 1 :width 20 :height 20}
|
||||
:source {:uri (contenthash/url (:hash content))}}]
|
||||
|
|
|
@ -65,16 +65,16 @@
|
|||
:title :t/recover-with-keycard
|
||||
:disabled? (not config/hardwallet-enabled?)
|
||||
:accessibility-label :recover-with-keycard-button
|
||||
:icon [react/view {:border-width 1
|
||||
:border-radius 20
|
||||
:border-color colors/blue-light
|
||||
:background-color colors/blue-light
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:width 40
|
||||
:height 40}
|
||||
[react/image {:source (resources/get-image :keycard-logo-blue)
|
||||
:style {:width 24 :height 24}}]]
|
||||
:icon [react/view {:border-width 1
|
||||
:border-radius 20
|
||||
:border-color colors/blue-light
|
||||
:background-color colors/blue-light
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:width 40
|
||||
:height 40}
|
||||
[react/image {:source (resources/get-image :keycard-logo-blue)
|
||||
:style {:width 24 :height 24}}]]
|
||||
:on-press #(re-frame/dispatch [::hardwallet/recover-with-keycard-pressed])}])]])
|
||||
|
||||
(defn bottom-sheet []
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
[status-im.ui.screens.profile.navigation]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.chat.models :as chat-models]
|
||||
[status-im.chat.commands.input :as commands-input]
|
||||
[status-im.utils.image-processing :as image-processing]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
@ -23,10 +22,8 @@
|
|||
"photo"))
|
||||
|
||||
(defn send-transaction [chat-id {:keys [db] :as cofx}]
|
||||
(let [send-command (get-in db [:id->command ["send" #{:personal-chats}]])]
|
||||
(fx/merge cofx
|
||||
(chat-models/start-chat chat-id {:navigation-reset? true})
|
||||
(commands-input/select-chat-input-command send-command nil))))
|
||||
;;TODO start send transaction command flow
|
||||
(chat-models/start-chat chat-id {:navigation-reset? true}))
|
||||
|
||||
(defn- valid-name? [name]
|
||||
(spec/valid? :profile/name name))
|
||||
|
|
|
@ -63,7 +63,10 @@
|
|||
[chat-icon/custom-icon-view-list (:name token) color 32])]}]
|
||||
[separator]]))
|
||||
|
||||
(defn header [{:keys [in-progress?] :as sign} {:keys [contact amount token approve?] :as tx} display-symbol fee fee-display-symbol]
|
||||
(defn header
|
||||
[{:keys [in-progress?] :as sign}
|
||||
{:keys [contact amount token approve?] :as tx}
|
||||
display-symbol fee fee-display-symbol]
|
||||
[react/view styles/header
|
||||
(when sign
|
||||
[react/touchable-highlight (when-not in-progress? {:on-press #(re-frame/dispatch [:set :signing/sign nil])})
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.send.views :as wallet.send]
|
||||
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
|
||||
[status-im.ui.screens.keycard.views :as keycard]
|
||||
[status-im.ui.screens.home.sheet.views :as home.sheet]
|
||||
|
|
|
@ -33,13 +33,4 @@
|
|||
[button/button
|
||||
{:on-press #(re-frame/dispatch [:wallet.accounts/share address])
|
||||
:label :t/share-address
|
||||
:accessibility-label :share-address-button}]]
|
||||
;;TODO temporary hide for v1
|
||||
#_[button/button
|
||||
{:on-press
|
||||
#(do
|
||||
(re-frame/dispatch [:hide-popover])
|
||||
(re-frame/dispatch [:navigate-to :wallet-send-transaction-request address]))
|
||||
:accessibility-label :sent-transaction-request-button
|
||||
:label :t/send-transaction-request
|
||||
:type :secondary}]]))
|
||||
:accessibility-label :share-address-button}]]]))
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
(ns status-im.test.chat.commands.core
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.commands.core :as core]
|
||||
[status-im.chat.commands.protocol :as protocol]))
|
||||
|
||||
(defn- fake-suggestion
|
||||
[selected-event-creator value]
|
||||
(selected-event-creator value))
|
||||
|
||||
(def test-command-parameters
|
||||
[{:id :first-param
|
||||
:type :text
|
||||
;; pass function as mock-up for suggestions component, so we can
|
||||
;; just test the correct injection of `:set-command-parameter` event
|
||||
:suggestions fake-suggestion}
|
||||
{:id :second-param
|
||||
:type :text}
|
||||
{:id :last-param
|
||||
:type :text
|
||||
:suggestions fake-suggestion}])
|
||||
|
||||
(deftype TestCommand []
|
||||
protocol/Command
|
||||
(id [_] "test-command")
|
||||
(scope [_] #{:personal-chats :group-chats :public-chats})
|
||||
(description [_] "Another test command")
|
||||
(parameters [_] test-command-parameters)
|
||||
(validate [_ parameters _]
|
||||
(when-not (every? (comp string? second) parameters)
|
||||
"Not all parameters are filled and of the correct type"))
|
||||
(on-send [_ _ _])
|
||||
(on-receive [_ _ _])
|
||||
(short-preview [_ command-message]
|
||||
[:text (str "Test-command, first-param: "
|
||||
(get-in command-message [:content :params :first-param]))])
|
||||
(preview [_ command-message]
|
||||
[:text (str "Test-command, params: "
|
||||
(apply str (map [:first-param :second-param :last-param]
|
||||
(get-in command-message [:content :params]))))]))
|
||||
|
||||
(def another-test-command-parameters
|
||||
[{:id :first-param
|
||||
:type :text}])
|
||||
|
||||
(deftype AnotherTestCommand []
|
||||
protocol/Command
|
||||
(id [_] "another-test-command")
|
||||
(scope [_] #{:public-chats})
|
||||
(description [_] "Another test command")
|
||||
(parameters [_] another-test-command-parameters)
|
||||
(validate [_ parameters _]
|
||||
(when-not (every? (comp string? second) parameters)
|
||||
"Not all parameters are filled and of the correct type"))
|
||||
(on-send [_ _ _])
|
||||
(on-receive [_ _ _])
|
||||
(short-preview [_ command-message]
|
||||
[:text (str "Test-command, first-param: "
|
||||
(get-in command-message [:content :params :first-param]))])
|
||||
(preview [_ command-message]
|
||||
[:text (str "Test-command, params: "
|
||||
(apply str (map [:first-param]
|
||||
(get-in command-message [:content :params]))))]))
|
||||
|
||||
(def TestCommandInstance (TestCommand.))
|
||||
(def AnotherTestCommandInstance (AnotherTestCommand.))
|
||||
|
||||
(deftest load-commands-test
|
||||
(let [fx (core/load-commands {:db {}} #{TestCommandInstance AnotherTestCommandInstance})]
|
||||
(testing "Primary composite key index for command is correctly created"
|
||||
(is (= TestCommandInstance
|
||||
(get-in fx [:db :id->command
|
||||
(core/command-id TestCommandInstance) :type]))))
|
||||
(testing "Access scope indexes are correctly created"
|
||||
(is (contains? (get-in fx [:db :access-scope->command-id #{:personal-chats}])
|
||||
(core/command-id TestCommandInstance)))
|
||||
(is (not (contains? (get-in fx [:db :access-scope->command-id #{:personal-chats}])
|
||||
(core/command-id AnotherTestCommandInstance))))
|
||||
(is (contains? (get-in fx [:db :access-scope->command-id #{:group-chats}])
|
||||
(core/command-id TestCommandInstance)))
|
||||
(is (contains? (get-in fx [:db :access-scope->command-id #{:public-chats}])
|
||||
(core/command-id TestCommandInstance)))
|
||||
(is (contains? (get-in fx [:db :access-scope->command-id #{:public-chats}])
|
||||
(core/command-id AnotherTestCommandInstance))))))
|
||||
|
||||
#_(deftest chat-commands-test
|
||||
(let [fx (core/load-commands {:db {}} #{TestCommandInstance AnotherTestCommandInstance})]
|
||||
(testing "That relevant commands are looked up for chat"
|
||||
(is (= #{TestCommandInstance AnotherTestCommandInstance}
|
||||
(into #{}
|
||||
(map (comp :type second))
|
||||
(core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "topic"
|
||||
:group-chat true
|
||||
:public? true}))))
|
||||
(is (= #{TestCommandInstance}
|
||||
(into #{}
|
||||
(map (comp :type second))
|
||||
(core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "group"
|
||||
:group-chat true}))))
|
||||
(is (= #{TestCommandInstance}
|
||||
(into #{}
|
||||
(map (comp :type second))
|
||||
(core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "contact"})))))))
|
||||
|
||||
(def contacts #{"0x0471b2be1e8b971f75b571ba047baa58e2f40f67dad38f6381b2382df43f7176b1813bf372af4cd8451ed9063213029378b9fbc7db792d496e1a6161c42d999edf"
|
||||
"0x04b790f2c3f4079f35a1fa396465ceb243cc446c9af211d0a1774f869eb9632a67a6e664e24075ec5c5a8a95a509a2a8173dbfeb88af372e784a37fecc1b5c0ba5"
|
||||
"0x04cc3cec3f88dc1a39e224388f0304023fc78c2a7d05e4ebd61638192cc592d2c13d8f081b5d9995dbfcbe45a4ca7eb80d5c505eee660e8fee0df2da222f047287"})
|
||||
|
||||
(def contacts_addresses '("0x5adf1b9e1fa4bd4889fecd598b45079045d98f0e"
|
||||
"0x21631d18d9681d4ffdd460fc45fa52159fcd95c8"
|
||||
"0x5541e3be81b76d76cdbf968516caa5a5b773763b"))
|
||||
|
||||
(deftest enrich-command-message-for-events-test-public
|
||||
(let [db {:chats {"1" {:contacts nil :public? true :group-chat false}}}
|
||||
msg {:chat-id "1"}
|
||||
enriched-msg (core/enrich-command-message-for-events db msg)]
|
||||
(testing "command-message correctly (not) enriched - public chat"
|
||||
(is (= enriched-msg
|
||||
(assoc msg :public? true :group-chat false))))))
|
||||
|
||||
(deftest enrich-command-message-for-events-test-groupchat
|
||||
(let [db {:chats {"1" {:contacts contacts :public? false :group-chat true}}}
|
||||
msg {:chat-id "1"}
|
||||
enriched-msg (core/enrich-command-message-for-events db msg)]
|
||||
(testing "command-message correctly enriched - group chat"
|
||||
(is (= enriched-msg
|
||||
(assoc msg :public? false :group-chat true :contacts contacts_addresses))))))
|
||||
|
||||
(deftest enrich-command-message-for-events-test-1on1-chat
|
||||
(let [db {:chats {"1" {:contacts contacts :public? false :group-chat false}}}
|
||||
msg {:chat-id "1"}
|
||||
enriched-msg (core/enrich-command-message-for-events db msg)]
|
||||
(testing "command-message correctly enriched - 1on1 chat"
|
||||
(is (= enriched-msg
|
||||
(assoc msg :public? false :group-chat false :contact (first contacts_addresses)))))))
|
|
@ -1,82 +0,0 @@
|
|||
(ns status-im.test.chat.commands.impl.transactions
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.commands.impl.transactions :as transactions]
|
||||
[status-im.chat.commands.protocol :as protocol]))
|
||||
|
||||
(def public-key "0x04f96bc2229a0ba4125815451e47491d9ab923b8b03f205f6ff11d731c0f5759079c1aa0f3b73233c114372695c30a8e20ce18f73fafa23f924736cc39e726c3de")
|
||||
(def address "f86b3cefae5851c19abfc48b7fb034b1dfa70b52")
|
||||
(def cofx {:db {:multiaccount {:settings {:wallet {:visible-tokens {:mainnet #{:SNT}}}}
|
||||
:wallet-set-up-passed? true}
|
||||
:chain "mainnet"
|
||||
:current-chat-id public-key
|
||||
:contacts/contacts {public-key {:name "Recipient"
|
||||
:address address
|
||||
:public-key public-key}}
|
||||
:wallet/all-tokens {:mainnet {"0x744d70fdbe2ba4cf95131626614a1763df805b9e" {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
:name "Status Network Token"
|
||||
:symbol :SNT
|
||||
:decimals 18}}}}})
|
||||
|
||||
;; testing the `/send` command
|
||||
|
||||
(def personal-send-command (transactions/PersonalSendCommand.))
|
||||
|
||||
(deftest personal-send-command-test
|
||||
(testing "That correct parameters are defined"
|
||||
(is (= (into #{} (map :id) (protocol/parameters personal-send-command))
|
||||
#{:asset :amount})))
|
||||
(testing "Parameters validation"
|
||||
(is (= (protocol/validate personal-send-command {:asset "TST"} cofx)
|
||||
{:title (i18n/label :t/send-request-invalid-asset)
|
||||
:description (i18n/label :t/send-request-unknown-token {:asset "TST"})}))
|
||||
(is (= (protocol/validate personal-send-command {:asset "SNT"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-must-be-specified)}))
|
||||
(is (= (protocol/validate personal-send-command {:asset "SNT" :amount "a"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-send-command {:asset "ETH" :amount "0.54354353454353453453454353453445345545"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-max-decimals {:asset-decimals 18})}))
|
||||
(is (= (protocol/validate personal-send-command {:asset "ETH" :amount "0.01"} cofx)
|
||||
nil))))
|
||||
|
||||
;; testing the `/request` command
|
||||
|
||||
(def personal-request-command (transactions/PersonalRequestCommand.))
|
||||
|
||||
(deftest personal-request-command-test
|
||||
(testing "That correct parameters are defined"
|
||||
(is (= (into #{} (map :id) (protocol/parameters personal-request-command))
|
||||
#{:asset :amount})))
|
||||
(testing "Parameters validation"
|
||||
(is (= (protocol/validate personal-request-command {:asset "TST"} cofx)
|
||||
{:title (i18n/label :t/send-request-invalid-asset)
|
||||
:description (i18n/label :t/send-request-unknown-token {:asset "TST"})}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "SNT"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-must-be-specified)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "SNT" :amount "a"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "ETH" :amount "0,1Aaa"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "ETH" :amount "1-45"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "SNT" :amount "1$#@8"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "SNT" :amount "20,"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "SNT" :amount "20."} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-invalid-number)}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "ETH" :amount "0.54354353454353453453454353453445345545"} cofx)
|
||||
{:title (i18n/label :t/send-request-amount)
|
||||
:description (i18n/label :t/send-request-amount-max-decimals {:asset-decimals 18})}))
|
||||
(is (= (protocol/validate personal-request-command {:asset "ETH" :amount "0.01"} cofx)
|
||||
nil))))
|
|
@ -1,80 +0,0 @@
|
|||
(ns status-im.test.chat.commands.input
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.test.chat.commands.core :as test-core]
|
||||
[status-im.chat.commands.core :as core]
|
||||
[status-im.chat.commands.input :as input]))
|
||||
|
||||
(deftest starts-as-command?-test
|
||||
(is (not (input/starts-as-command? nil)))
|
||||
(is (not (input/command-ends-with-space? "")))
|
||||
(is (not (input/command-ends-with-space? "word1 word2 word3")))
|
||||
(is (input/command-ends-with-space? "word1 word2 ")))
|
||||
|
||||
(deftest split-command-args-test
|
||||
(is (nil? (input/split-command-args nil)))
|
||||
(is (= [""] (input/split-command-args "")))
|
||||
(is (= ["@browse" "google.com"] (input/split-command-args "@browse google.com")))
|
||||
(is (= ["@browse" "google.com"] (input/split-command-args " @browse google.com ")))
|
||||
(is (= ["/send" "1.0" "John Doe"] (input/split-command-args "/send 1.0 \"John Doe\"")))
|
||||
(is (= ["/send" "1.0" "John Doe"] (input/split-command-args "/send 1.0 \"John Doe\" "))))
|
||||
|
||||
(deftest join-command-args-test
|
||||
(is (nil? (input/join-command-args nil)))
|
||||
(is (= "" (input/join-command-args [""])))
|
||||
(is (= "/send 1.0 \"John Doe\"" (input/join-command-args ["/send" "1.0" "John Doe"]))))
|
||||
|
||||
#_(deftest selected-chat-command-test
|
||||
(let [fx (core/load-commands {:db {}} #{test-core/TestCommandInstance test-core/AnotherTestCommandInstance})
|
||||
commands (core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "contact"})]
|
||||
(testing "Text not beggining with the command special charactes `/` is recognised"
|
||||
(is (not (input/selected-chat-command "test-command 1" nil commands))))
|
||||
(testing "Command not matching any available commands is not recognised as well"
|
||||
(is (not (input/selected-chat-command "/another-test-command" nil commands))))
|
||||
(testing "Available correctly entered command is recognised"
|
||||
(is (= test-core/TestCommandInstance
|
||||
(get (input/selected-chat-command "/test-command" nil commands) :type))))
|
||||
(testing "Command completion and param position are determined as well"
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(input/selected-chat-command "/test-command 1 " 17 commands)]
|
||||
(is (= 1 current-param-position))
|
||||
(is (= :less-then-needed command-completion)))
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(input/selected-chat-command "/test-command 1 2 3" 20 commands)]
|
||||
(is (= 2 current-param-position))
|
||||
(is (= :complete command-completion))))))
|
||||
|
||||
(deftest set-command-parameter-test
|
||||
(testing "Setting command parameter correctly updates the text input"
|
||||
(let [create-cofx (fn [input-text]
|
||||
{:db {:chats {"test" {:input-text input-text}}
|
||||
:current-chat-id "test"}})]
|
||||
(is (= "/test-command first-value "
|
||||
(get-in (input/set-command-parameter (create-cofx "/test-command")
|
||||
false 0 "first-value")
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (input/set-command-parameter (create-cofx "/test-command first-value edited \"last value\"")
|
||||
false 1 "second-value")
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (input/set-command-parameter (create-cofx "/test-command first-value second-value")
|
||||
true 2 "last value")
|
||||
[:db :chats "test" :input-text]))))))
|
||||
|
||||
(deftest parse-parameters-test
|
||||
(testing "testing that parse-parameters work correctly"
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"
|
||||
:last-param "3"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 2 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2 2"
|
||||
:last-param "3"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 \"2 2\" 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 2")))
|
||||
(is (= {}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command ")))))
|
|
@ -2,9 +2,6 @@
|
|||
(:require [doo.runner :refer-macros [doo-tests]]
|
||||
[status-im.test.browser.core]
|
||||
[status-im.test.browser.permissions]
|
||||
[status-im.test.chat.commands.core]
|
||||
[status-im.test.chat.commands.impl.transactions]
|
||||
[status-im.test.chat.commands.input]
|
||||
[status-im.test.chat.db]
|
||||
[status-im.test.chat.models.input]
|
||||
[status-im.test.chat.models.message]
|
||||
|
@ -78,9 +75,6 @@
|
|||
(doo-tests
|
||||
'status-im.test.browser.core
|
||||
'status-im.test.browser.permissions
|
||||
'status-im.test.chat.commands.core
|
||||
'status-im.test.chat.commands.impl.transactions
|
||||
'status-im.test.chat.commands.input
|
||||
'status-im.test.chat.db
|
||||
'status-im.test.chat.models
|
||||
'status-im.test.chat.models.input
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
(ns status-im.test.ui.screens.currency-settings.models
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.commands.impl.transactions :as txs]
|
||||
[status-im.ui.screens.currency-settings.models :as models]))
|
||||
|
||||
(deftest get-currency
|
||||
(is (= :usd (txs/get-currency {:multiaccount {:settings {:wallet {:currency :usd}}}})))
|
||||
(is (= :usd (txs/get-currency {:multiaccount {:settings {:wallet {:currency nil}}}})))
|
||||
(is (= :usd (txs/get-currency {:multiaccount {:settings {:wallet {}}}})))
|
||||
(is (= :aud (txs/get-currency {:multiaccount {:settings {:wallet {:currency :aud}}}}))))
|
||||
(is (= :usd (models/get-currency {:multiaccount {:settings {:wallet {:currency :usd}}}})))
|
||||
(is (= :usd (models/get-currency {:multiaccount {:settings {:wallet {:currency nil}}}})))
|
||||
(is (= :usd (models/get-currency {:multiaccount {:settings {:wallet {}}}})))
|
||||
(is (= :aud (models/get-currency {:multiaccount {:settings {:wallet {:currency :aud}}}}))))
|
||||
|
||||
(deftest set-currency
|
||||
(let [cofx (models/set-currency {:db {:multiaccount {:settings {:wallet {}}}}} :usd)]
|
||||
|
|
Loading…
Reference in New Issue