diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 6d9e484fd2..126947a987 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -64,7 +64,8 @@ db (let [messages-path [:chats current-chat-id :messages] messages (get-in db messages-path) - new-messages (messages/get-by-chat-id current-chat-id (count messages)) + chat-messages (filter #(= current-chat-id (:chat-id %)) messages) + new-messages (messages/get-by-chat-id current-chat-id (count chat-messages)) all-loaded? (> default-number-of-messages (count new-messages))] (-> db (assoc :loading-allowed false) diff --git a/src/status_im/chat/handlers/receive_message.cljs b/src/status_im/chat/handlers/receive_message.cljs index a6b49b2120..ae84d19b01 100644 --- a/src/status_im/chat/handlers/receive_message.cljs +++ b/src/status_im/chat/handlers/receive_message.cljs @@ -5,7 +5,8 @@ [status-im.chat.utils :as cu] [status-im.commands.utils :refer [generate-hiccup]] [status-im.utils.random :as random] - [status-im.constants :refer [content-type-command-request]] + [status-im.constants :refer [wallet-chat-id + content-type-command-request]] [cljs.reader :refer [read-string]] [status-im.data-store.chats :as chats] [taoensso.timbre :as log])) @@ -25,8 +26,10 @@ [{:keys [current-account-id accounts]}] (:public-key (accounts current-account-id))) -(defn receive-message - [db [_ {:keys [from group-id chat-id message-id timestamp clock-value] :as message :or {clock-value 0}}]] +(declare add-message-to-wallet) + +(defn add-message + [db {:keys [from group-id chat-id message-id timestamp clock-value] :as message :or {clock-value 0}}] (let [same-message (messages/get-by-id message-id) current-identity (get-current-identity db) chat-id' (or group-id chat-id from) @@ -40,22 +43,31 @@ (when (and (not same-message) (not= from current-identity) (or (not exists?) active?)) - (let [group-chat? (not (nil? group-id)) + (let [group-chat? (not (nil? group-id)) previous-message (messages/get-last-message chat-id') - message' (assoc (->> message - (cu/check-author-direction previous-message) - (check-preview)) - :chat-id chat-id' - :timestamp (or timestamp (random/timestamp)) - :clock-value clock-value)] + message' (assoc (->> message + (cu/check-author-direction previous-message) + (check-preview)) + :chat-id chat-id' + :timestamp (or timestamp (random/timestamp)) + :clock-value clock-value)] (store-message message') (dispatch [:upsert-chat! {:chat-id chat-id' :group-chat group-chat? :clock-value clock-value}]) - (dispatch [::add-message message']) + (dispatch [::add-message chat-id message']) (when (= (:content-type message') content-type-command-request) (dispatch [:add-request chat-id' message'])) - (dispatch [:add-unviewed-message chat-id' message-id]))))) + (dispatch [:add-unviewed-message chat-id' message-id])) + (if (and (not= chat-id wallet-chat-id) + (= "send" (get-in message [:content :command]))) + (add-message-to-wallet db message))))) + +(defn add-message-to-wallet [db message] + (let [message' (assoc message :clock-value 0 + :message-id (random/id) + :chat-id wallet-chat-id)] + (add-message db message'))) (register-handler :received-protocol-message! (u/side-effect! @@ -66,8 +78,10 @@ :chat-id from})])))) (register-handler :received-message - (u/side-effect! receive-message)) + (u/side-effect! + (fn [db [_ message]] + (add-message db message)))) (register-handler ::add-message - (fn [db [_ {:keys [chat-id new?] :as message}]] - (cu/add-message-to-db db chat-id message new?))) + (fn [db [_ add-to-chat-id {:keys [chat-id new?] :as message}]] + (cu/add-message-to-db db add-to-chat-id chat-id message new?))) diff --git a/src/status_im/chat/handlers/send_message.cljs b/src/status_im/chat/handlers/send_message.cljs index e3fac15704..97786953f3 100644 --- a/src/status_im/chat/handlers/send_message.cljs +++ b/src/status_im/chat/handlers/send_message.cljs @@ -14,7 +14,7 @@ [status-im.utils.datetime :as datetime] [status-im.protocol.core :as protocol] [taoensso.timbre :refer-macros [debug] :as log] - [status-im.constants :refer [console-chat-id]] + [status-im.constants :refer [console-chat-id wallet-chat-id]] [status-im.chat.handlers.console :as console])) (defn prepare-command @@ -76,7 +76,7 @@ (dispatch [::invoke-command-handlers! params']) :else - (dispatch [:prepare-command! params']))))) + (dispatch [:prepare-command! chat-id params']))))) (when-not (s/blank? message) (dispatch [::prepare-message params]))))) @@ -88,13 +88,19 @@ (register-handler :prepare-command! (u/side-effect! (fn [{:keys [current-public-key] :as db} - [_ {:keys [chat-id staged-command handler-data] :as params}]] - (let [{:keys [clock-value]} (get-in db [:chats chat-id]) + [_ add-to-chat-id {:keys [chat-id staged-command handler-data] :as params}]] + (let [{:keys [clock-value]} (get-in db [:chats add-to-chat-id]) command' (->> (assoc staged-command :handler-data handler-data) (prepare-command current-public-key chat-id clock-value) (cu/check-author-direction db chat-id))] (dispatch [:clear-command chat-id (:id staged-command)]) - (dispatch [::send-command! (assoc params :command command')]))))) + (dispatch [::send-command! add-to-chat-id (assoc params :command command')]) + + (when (and (= "send" (get-in staged-command [:command :name])) + (not= add-to-chat-id wallet-chat-id)) + (let [staged-command' (assoc staged-command :id (random/id)) + params' (assoc params :staged-command staged-command')] + (dispatch [:prepare-command! wallet-chat-id params']))))))) (register-handler :clear-command (fn [db [_ chat-id id]] @@ -104,21 +110,22 @@ (register-handler ::send-command! (u/side-effect! - (fn [_ [_ params]] - (dispatch [::add-command params]) - (dispatch [::save-command! params]) - (dispatch [::dispatch-responded-requests! params]) - (dispatch [::send-command-protocol! params])))) + (fn [_ [_ add-to-chat-id params]] + (dispatch [::add-command add-to-chat-id params]) + (dispatch [::save-command! add-to-chat-id params]) + (when (not= add-to-chat-id wallet-chat-id) + (dispatch [::dispatch-responded-requests! params]) + (dispatch [::send-command-protocol! params]))))) (register-handler ::add-command - (after (fn [_ [_ {:keys [handler]}]] + (after (fn [_ [_ _ {:keys [handler]}]] (when handler (handler)))) - (fn [db [_ {:keys [chat-id command]}]] - (cu/add-message-to-db db chat-id command))) + (fn [db [_ add-to-chat-id {:keys [chat-id command]}]] + (cu/add-message-to-db db add-to-chat-id chat-id command))) (register-handler ::save-command! (u/side-effect! - (fn [_ [_ {:keys [command chat-id]}]] + (fn [_ [_ chat-id {:keys [command]}]] (messages/save chat-id (dissoc command :rendered-preview :to-message :has-handler))))) @@ -178,7 +185,7 @@ (register-handler ::add-message (fn [db [_ {:keys [chat-id message]}]] - (cu/add-message-to-db db chat-id message))) + (cu/add-message-to-db db chat-id chat-id message))) (register-handler ::save-message! (after (fn [_ [_ params]] diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index 17468771d1..51bfd8f0d6 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -9,6 +9,7 @@ [status-im.chat.views.plain-message :as plain-message] [status-im.chat.views.command :as command] [status-im.constants :refer [content-type-status]] + [status-im.chat.utils :as cu] [status-im.utils.datetime :as time] [status-im.utils.platform :refer [platform-specific]] [taoensso.timbre :as log])) @@ -61,11 +62,13 @@ (reaction (or (get-in @db [:chats current-chat :responses]) {}))))) (register-sub :get-commands-and-responses - (fn [db _] - (let [current-chat (@db :current-chat-id)] - (reaction _ (or (->> (get-in @db [:chats current-chat]) - ((juxt :commands :responses)) - (apply merge)) {}))))) + (fn [db [_ chat-id]] + (reaction (or (->> (get-in @db [:chats chat-id]) + ((juxt :commands :responses)) + (apply merge)) + (->> (get @db :all-commands) + ((juxt :commands :responses)) + (apply merge)))))) (register-sub :get-chat-input-text (fn [db _] diff --git a/src/status_im/chat/utils.cljs b/src/status_im/chat/utils.cljs index 42679a7f69..54e7be2c32 100644 --- a/src/status_im/chat/utils.cljs +++ b/src/status_im/chat/utils.cljs @@ -1,5 +1,7 @@ (ns status-im.chat.utils - (:require [status-im.constants :refer [console-chat-id]])) + (:require [status-im.constants :refer [console-chat-id + wallet-chat-id]] + [taoensso.timbre :as log])) (defn console? [s] (= console-chat-id s)) @@ -7,10 +9,13 @@ (def not-console? (complement console?)) +(defn wallet? [s] + (= wallet-chat-id s)) + (defn add-message-to-db - ([db chat-id message] (add-message-to-db db chat-id message true)) - ([db chat-id message new?] - (let [messages [:chats chat-id :messages]] + ([db add-to-chat-id chat-id message] (add-message-to-db db add-to-chat-id chat-id message true)) + ([db add-to-chat-id chat-id message new?] + (let [messages [:chats add-to-chat-id :messages]] (update-in db messages conj (assoc message :chat-id chat-id :new? (if (nil? new?) true diff --git a/src/status_im/chat/views/message.cljs b/src/status_im/chat/views/message.cljs index 3f956cdb8e..c44562dba4 100644 --- a/src/status_im/chat/views/message.cljs +++ b/src/status_im/chat/views/message.cljs @@ -20,6 +20,7 @@ [status-im.resources :as res] [status-im.utils.datetime :as time] [status-im.constants :refer [console-chat-id + wallet-chat-id text-content-type content-type-status content-type-command @@ -30,7 +31,8 @@ [status-im.i18n :refer [label]] [status-im.chat.utils :as cu] [clojure.string :as str] - [status-im.chat.handlers.console :as console])) + [status-im.chat.handlers.console :as console] + [taoensso.timbre :as log])) (defn message-content-status [_] (let [{:keys [chat-id group-chat name color]} (subscribe [:chat-properties [:chat-id :group-chat :name :color]]) @@ -72,8 +74,36 @@ :font :default} "03:39"]]]) -(defview message-content-command [content preview] - [commands [:get-commands-and-responses]] +(defmulti command-preview (fn [{:keys [command]}] command)) + +(defmethod command-preview "send" + [{{:keys [name]} :contact-chat + :keys [contact-address params outgoing? current-chat-id]}] + (let [amount (if (= 1 (count params)) + (first (vals params)) + (str params))] + [text {:style st/command-text + :font :default} + (if (= current-chat-id wallet-chat-id) + (let [label-val (if outgoing? :t/chat-send-eth-to :t/chat-send-eth-from)] + (label label-val {:amount amount + :chat-name (or name contact-address)})) + (label :t/chat-send-eth {:amount amount}))])) + +(defmethod command-preview :default + [{:keys [params preview]}] + (if preview + preview + [text {:style st/command-text + :font :default} + (if (= 1 (count params)) + (first (vals params)) + (str params))])) + +(defview message-content-command [{:keys [content rendered-preview chat-id to from outgoing] :as message}] + [commands [:get-commands-and-responses (if outgoing to from)] + current-chat-id [:get-current-chat-id] + contact-chat [:get-in [:chats (if outgoing to from)]]] (let [{:keys [command params]} (parse-command-message-content commands content) {:keys [name type] icon-path :icon} command] @@ -86,13 +116,13 @@ (when icon-path [view st/command-image-view [icon icon-path st/command-image]]) - (if preview - preview - [text {:style st/command-text - :font :default} - (if (= 1 (count params)) - (first (vals params)) - (str params))])])) + [command-preview {:command (:name command) + :params params + :outgoing? outgoing + :preview rendered-preview + :contact-chat contact-chat + :contact-address (if outgoing to from) + :current-chat-id current-chat-id}]])) (defn set-chat-command [message-id command] (dispatch [:set-response-chat-command message-id (keyword (:name command))])) @@ -147,9 +177,9 @@ [message-content-status message]) (defmethod message-content content-type-command - [wrapper {:keys [content rendered-preview] :as message}] + [wrapper message] [wrapper message - [message-view message [message-content-command content rendered-preview]]]) + [message-view message [message-content-command message]]]) (defmethod message-content :default [wrapper {:keys [content-type content] :as message}] @@ -206,10 +236,15 @@ [app-db-message-status-value [:get-in [:message-statuses message-id :status]]] (let [delivery-status (get-in user-statuses [chat-id :status]) command-name (keyword (:command content)) - status (if (and (not (console/commands-with-delivery-status command-name)) - (cu/console? chat-id)) - :seen - (or delivery-status message-status app-db-message-status-value :sending))] + status (cond (and (not (console/commands-with-delivery-status command-name)) + (cu/console? chat-id)) + :seen + + (cu/wallet? chat-id) + :sent + + :else + (or delivery-status message-status app-db-message-status-value :sending))] [view st/delivery-view [image {:source (case status :seen {:uri :icon_ok_small} diff --git a/src/status_im/commands/handlers/jail.cljs b/src/status_im/commands/handlers/jail.cljs index 4cd1c74ab7..1d81de59b3 100644 --- a/src/status_im/commands/handlers/jail.cljs +++ b/src/status_im/commands/handlers/jail.cljs @@ -32,10 +32,10 @@ parameters' (assoc parameters :command command')] (if (:eth_sendTransaction context) (dispatch [:wait-for-transaction (:id staged-command) parameters']) - (dispatch [:prepare-command! parameters']))) + (dispatch [:prepare-command! chat-id parameters']))) (not (or error handler-error)) - (dispatch [:prepare-command! parameters]) + (dispatch [:prepare-command! chat-id parameters]) :else nil))) diff --git a/src/status_im/commands/handlers/loading.cljs b/src/status_im/commands/handlers/loading.cljs index 58362fb0ac..390a31fff5 100644 --- a/src/status_im/commands/handlers/loading.cljs +++ b/src/status_im/commands/handlers/loading.cljs @@ -61,7 +61,9 @@ (let [{:keys [error result]} (json->clj result)] (if error (dispatch [::loading-failed! identity ::error-in-jail error]) - (dispatch [::add-commands identity file result])))))) + (if identity + (dispatch [::add-commands identity file result]) + (dispatch [::add-all-commands result]))))))) (defn validate-hash [db [identity file]] @@ -126,6 +128,11 @@ (dispatch [:invoke-commands-loading-callbacks id])))] add-commands) +(reg-handler ::add-all-commands + (fn [db [{:keys [commands responses]}]] + (assoc db :all-commands {:commands (mark-as :command commands) + :responses (mark-as :response responses)}))) + (reg-handler ::loading-failed! (u/side-effect! loading-failed!)) (reg-handler :add-commands-loading-callback diff --git a/src/status_im/data_store/contacts.cljs b/src/status_im/data_store/contacts.cljs index 150ea20e56..714e8d0fdb 100644 --- a/src/status_im/data_store/contacts.cljs +++ b/src/status_im/data_store/contacts.cljs @@ -1,5 +1,6 @@ (ns status-im.data-store.contacts - (:require [status-im.data-store.realm.contacts :as data-store]) + (:require [status-im.data-store.realm.contacts :as data-store] + [taoensso.timbre :as log]) (:refer-clojure :exclude [exists?])) (defn get-all diff --git a/src/status_im/data_store/messages.cljs b/src/status_im/data_store/messages.cljs index 210dc929b8..502e0c7b1d 100644 --- a/src/status_im/data_store/messages.cljs +++ b/src/status_im/data_store/messages.cljs @@ -5,7 +5,8 @@ [clojure.walk :refer [stringify-keys keywordize-keys]] [status-im.commands.utils :refer [generate-hiccup]] [cljs.reader :refer [read-string]] - [status-im.constants :as c]) + [status-im.constants :as c] + [taoensso.timbre :as log]) (:refer-clojure :exclude [update])) (defn- map-to-str @@ -46,6 +47,21 @@ (some-> (data-store/get-by-id message-id) (clojure.core/update :user-statuses user-statuses-to-map))) +(defn get-messages + [messages] + (->> messages + (mapv #(clojure.core/update % :user-statuses user-statuses-to-map)) + (into '()) + reverse + (keep (fn [{:keys [content-type preview] :as message}] + (if (command-type? content-type) + (-> message + (clojure.core/update :content str-to-map) + (assoc :rendered-preview + (when preview + (generate-hiccup (read-string preview))))) + message))))) + (defn get-by-chat-id ([chat-id] (get-by-chat-id chat-id 0)) diff --git a/src/status_im/data_store/realm/messages.cljs b/src/status_im/data_store/realm/messages.cljs index 3fe3c6837f..e153715303 100644 --- a/src/status_im/data_store/realm/messages.cljs +++ b/src/status_im/data_store/realm/messages.cljs @@ -27,6 +27,13 @@ (realm/page from (+ from number-of-messages)) (realm/realm-collection->list)))) +(defn get-by-fields + [fields from number-of-messages] + (-> (realm/get-by-fields @realm/account-realm :message :and fields) + (realm/sorted :timestamp :desc) + (realm/page from (+ from number-of-messages)) + (realm/realm-collection->list))) + (defn get-last-message [chat-id] (-> (realm/get-by-field @realm/account-realm :message :chat-id chat-id) diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index 783f8381b1..9af4d6877b 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -72,7 +72,8 @@ (dispatch [:load-accounts]) (dispatch [:init-console-chat]) (dispatch [:init-wallet-chat]) - (dispatch [:load-commands! console-chat-id])))) + (dispatch [:load-commands! console-chat-id]) + (dispatch [:load-commands!])))) (def ecc (js/require "eccjs")) diff --git a/src/status_im/transactions/handlers.cljs b/src/status_im/transactions/handlers.cljs index d60112aa36..d5f7d565e2 100644 --- a/src/status_im/transactions/handlers.cljs +++ b/src/status_im/transactions/handlers.cljs @@ -152,9 +152,9 @@ (register-handler ::send-pending-message (u/side-effect! (fn [{:keys [transaction-subscribers]} [_ message-id hash]] - (when-let [params (transaction-subscribers message-id)] + (when-let [{:keys [chat-id] :as params} (transaction-subscribers message-id)] (let [params' (assoc-in params [:handler-data :transaction-hash] hash)] - (dispatch [:prepare-command! params'])) + (dispatch [:prepare-command! chat-id params'])) (dispatch [::remove-transaction-subscriber message-id]))))) (register-handler ::remove-transaction-subscriber diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 735442302f..b02e68d269 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -142,6 +142,9 @@ :keypair-password-command-description "" :help-command-description "Help" :request "Request" + :chat-send-eth "{{amount}} ETH" + :chat-send-eth-to "{{amount}} ETH to {{chat-name}}" + :chat-send-eth-from "{{amount}} ETH from {{chat-name}}" :command-text-location "Location: {{address}}" :command-text-browse "Browsing webpage: {{webpage}}" :command-text-send "Transaction: {{amount}} ETH"