diff --git a/src/status_im/chat/events/input.cljs b/src/status_im/chat/events/input.cljs index 116a7606f4..432bf7b03d 100644 --- a/src/status_im/chat/events/input.cljs +++ b/src/status_im/chat/events/input.cljs @@ -8,6 +8,7 @@ [status-im.chat.models.input :as input-model] [status-im.chat.events.commands :as commands-events] [status-im.chat.events.animation :as animation-events] + [status-im.chat.events.send-message :as send-message-events] [status-im.bots.events :as bots-events] [status-im.ui.components.react :as react-comp] [status-im.utils.datetime :as time] @@ -440,8 +441,11 @@ (handlers/register-handler-fx :send-current-message - [(re-frame/inject-cofx :random-id)] - (fn [{{:keys [current-chat-id current-public-key] :as db} :db message-id :random-id current-time :now} _] + [(re-frame/inject-cofx :random-id) + (re-frame/inject-cofx :get-last-clock-value) + (re-frame/inject-cofx :get-stored-chat)] + (fn [{{:keys [current-chat-id current-public-key] :as db} :db message-id :random-id current-time :now + :as cofx} _] (let [input-text (get-in db [:chats current-chat-id :input-text]) chat-command (-> (input-model/selected-chat-command db) (as-> selected-command @@ -464,14 +468,13 @@ ;; no command detected, when not empty, proceed by sending text message without command processing (if (str/blank? input-text) {:db db} - {:db (-> db - (set-chat-input-metadata nil) - (set-chat-input-text nil)) - ;; TODO: refactor send-message.cljs to use atomic pure handlers and get rid of this dispatch - :dispatch [:prepare-message {:message input-text - :chat-id current-chat-id - :identity current-public-key - :address (:accounts/current-account-id db)}]}))))) + (send-message-events/prepare-message (assoc cofx :db (-> db + (set-chat-input-metadata nil) + (set-chat-input-text nil))) + {:message-text input-text + :chat-id current-chat-id + :identity current-public-key + :address (:accounts/current-account-id db)})))))) ;; TODO: remove this handler and leave only helper fn once all invocations are refactored (handlers/register-handler-db diff --git a/src/status_im/chat/events/send_message.cljs b/src/status_im/chat/events/send_message.cljs new file mode 100644 index 0000000000..bcd03fc7e5 --- /dev/null +++ b/src/status_im/chat/events/send_message.cljs @@ -0,0 +1,103 @@ +(ns status-im.chat.events.send-message + (:require [re-frame.core :as re-frame] + [status-im.utils.handlers :as handlers] + [status-im.constants :as constants] + [status-im.utils.clocks :as clocks] + [status-im.utils.config :as config] + [status-im.chat.models :as chat.models] + [status-im.chat.utils :as chat.utils] + [status-im.protocol.core :as protocol] + [status-im.native-module.core :as status] + [taoensso.timbre :as log])) + +(re-frame/reg-fx + ::send-notification + (fn [fcm-token] + (log/debug "send-notification fcm-token: " fcm-token) + (status/notify fcm-token #(log/debug "send-notification cb result: " %)))) + +(re-frame/reg-fx + ::send-message + (fn [message] + (protocol/send-message! message))) + +(re-frame/reg-fx + ::send-group-message + (fn [message] + (protocol/send-group-message! message))) + +(re-frame/reg-fx + ::send-public-group-message + (fn [message] + (protocol/send-public-group-message! message))) + +(defn- send-message + [{:keys [web3 network-status local-storage chats] + :contacts/keys [contacts] + :as db} + {:keys [message-type content from chat-id to] :as message}] + (let [{:keys [dapp? fcm-token]} (get contacts chat-id) + {:keys [public-key private-key]} (get chats chat-id) + sender-name (get-in contacts [from :name])] + ;; whenever we are sending message to DApp, we are assuming it's a status bot, + ;; so we are just calling jail `on-message-send` function + (when message + (if dapp? + {:call-jail-function {:chat-id chat-id + :function :on-message-send + :parameters {:message content} + :content {:data (get local-storage chat-id) + :from from}}} + (let [payload (select-keys message [:timestamp :content :content-type + :clock-value :show?]) + message-to-send {:web3 web3 + :message (-> (select-keys message [:message-id :from]) + (assoc :payload (if (= :offline network-status) + (assoc payload :show? false) + payload)))}] + (case message-type + :group-user-message {::send-group-message + (assoc message-to-send + :group-id chat-id + :keypair {:public public-key + :private private-key})} + :public-group-user-message {::send-public-group-message + (assoc message-to-send + :group-id chat-id + :username sender-name)} + :user-message (cond-> {::send-message + (assoc-in message-to-send + [:message :to] to)} + (and fcm-token config/notifications-wip-enabled?) + (assoc ::send-notification fcm-token)))))))) + +(defn prepare-message + [{:keys [db now random-id get-last-clock-value] :as cofx} + {:keys [chat-id identity message-text] :as params}] + (let [{:keys [group-chat public?]} (get-in db [:chats chat-id]) + message (cond-> {:message-id random-id + :chat-id chat-id + :content message-text + :from identity + :content-type constants/text-content-type + :outgoing true + :timestamp now + :clock-value (clocks/send (get-last-clock-value chat-id)) + :show? true} + (not group-chat) + (assoc :message-type :user-message + :to chat-id) + group-chat + (assoc :group-id chat-id) + (and group-chat public?) + (assoc :message-type :public-group-user-message) + (and group-chat (not public?)) + (assoc :message-type :group-user-message))] + (as-> (chat.models/upsert-chat cofx {:chat-id chat-id}) + fx (merge fx + {:db (chat.utils/add-message-to-db (:db fx) chat-id chat-id message) + :save-message message + ;; TODO janherich - get rid of this, there is absolutely no reason why it can't be just + ;; plain app-db inc + chat update + :dispatch [:update-message-overhead! chat-id (:network-status db)]} + (send-message (:db fx) message))))) diff --git a/src/status_im/chat/handlers/send_message.cljs b/src/status_im/chat/handlers/send_message.cljs index 4f7c2031b8..e67a962b2a 100644 --- a/src/status_im/chat/handlers/send_message.cljs +++ b/src/status_im/chat/handlers/send_message.cljs @@ -166,57 +166,6 @@ (fn [res] (dispatch [:command-handler! chat-id orig-params res])))}))))) -(register-handler :prepare-message - (u/side-effect! - (fn [{:keys [network-status] :as db} [_ {:keys [chat-id identity message] :as params}]] - (let [{:keys [group-chat public?]} (get-in db [:chats chat-id]) - clock-value (messages/get-last-clock-value chat-id) - message' {:message-id (random/id) - :chat-id chat-id - :content message - :from identity - :content-type text-content-type - :outgoing true - :timestamp (datetime/now-ms) - :clock-value (clocks/send clock-value) - :show? true} - message'' (cond-> message' - (and group-chat public?) - (assoc :group-id chat-id :message-type :public-group-user-message) - (and group-chat (not public?)) - (assoc :group-id chat-id :message-type :group-user-message) - (not group-chat) - (assoc :to chat-id :message-type :user-message)) - params' (assoc params :message message'')] - (dispatch [:update-message-overhead! chat-id network-status]) - (dispatch [::add-message params']) - (dispatch [::save-message! params']))))) - -(register-handler ::add-message - (fn [db [_ {:keys [chat-id message]}]] - (cu/add-message-to-db db chat-id chat-id message))) - -(register-handler - ::save-message! - (after (fn [_ [_ params]] - (dispatch [::send-message! params]))) - (u/side-effect! - (fn [_ [_ {:keys [chat-id message]}]] - (dispatch [:upsert-chat! {:chat-id chat-id}]) - (messages/save message)))) - -(register-handler - ::send-dapp-message - (u/side-effect! - (fn [{:accounts/keys [current-account-id] :as db} [_ chat-id {:keys [content]}]] - (let [data (get-in db [:local-storage chat-id])] - (status/call-function! - {:chat-id chat-id - :function :on-message-send - :parameters {:message content} - :context {:data data - :from current-account-id}}))))) - (register-handler :received-bot-response (u/side-effect! @@ -287,53 +236,6 @@ {:result result :chat-id chat-id}]))))) -(defn send-notification [fcm-token message] - (if (and fcm-token config/notifications-wip-enabled?) - (do (log/debug "send-notification fcm-token: " fcm-token) - (log/debug "send-notification message: " message) - (status/notify fcm-token (fn [res] - (log/debug "send-notification cb result: " res)))) - (log/debug "send-notification message not sending because fcm-token is unavailable or notification flag is off"))) - -(register-handler ::send-message! - (u/side-effect! - (fn [{:keys [web3 chats network-status] - :accounts/keys [accounts current-account-id] - :contacts/keys [contacts] - :as db} [_ {{:keys [message-type] - :as message} :message - chat-id :chat-id}]] - (let [{:keys [dapp? fcm-token]} (get contacts chat-id)] - (if dapp? - (dispatch [::send-dapp-message chat-id message]) - (when message - (let [message' (select-keys message [:from :message-id]) - payload (select-keys message [:timestamp :content :content-type - :clock-value :show?]) - payload (if (= network-status :offline) - (assoc payload :show? false) - payload) - options {:web3 web3 - :message (assoc message' :payload payload)}] - (cond - (= message-type :group-user-message) - (let [{:keys [public-key private-key]} (chats chat-id)] - (protocol/send-group-message! (assoc options - :group-id chat-id - :keypair {:public public-key - :private private-key}))) - - (= message-type :public-group-user-message) - (protocol/send-public-group-message! - (let [username (get-in accounts [current-account-id :name])] - (assoc options :group-id chat-id - :username username))) - - :else - (do (protocol/send-message! (assoc-in options - [:message :to] (:to message))) - (send-notification fcm-token (:message options))))))))))) - (register-handler ::send-command-protocol! (u/side-effect! (fn [{:keys [web3 current-public-key chats network-status]