diff --git a/src/status_im/chat/console.cljs b/src/status_im/chat/console.cljs new file mode 100644 index 0000000000..e71451cf56 --- /dev/null +++ b/src/status_im/chat/console.cljs @@ -0,0 +1,104 @@ +(ns status-im.chat.console + (:require [status-im.ui.components.styles :refer [default-chat-color]] + [status-im.utils.random :as random] + [status-im.constants :as const] + [status-im.chat.constants :as chat-const] + [status-im.i18n :as i18n] + [clojure.string :as string])) + +(defn console-message [{:keys [message-id content content-type] + :or {message-id (random/id)}}] + {:message-id message-id + :outgoing false + :chat-id const/console-chat-id + :from const/console-chat-id + :to "me" + :content content + :content-type content-type}) + + +(def enter-confirmation-code-message + (console-message {:content {:command "confirmation-code" + :content (i18n/label :t/confirmation-code)} + :content-type const/content-type-command-request})) + +(def incorrect-confirmation-code-message + (console-message {:content {:command "confirmation-code" + :content (i18n/label :t/incorrect-code)} + :content-type const/content-type-command-request})) + +(def contacts-synchronised-message + (console-message {:content (i18n/label :t/contacts-syncronized) + :content-type const/text-content-type})) + +(def phone-number-request-message + (console-message {:content {:command "phone" + :content (i18n/label :t/phone-number-required)} + :content-type const/content-type-command-request})) + +(def shake-your-phone-message + (console-message {:content (i18n/label :t/shake-your-phone) + :content-type const/text-content-type})) + +(def account-generation-message + (console-message {:message-id chat-const/crazy-math-message-id + :content (i18n/label :t/account-generation-message) + :content-type const/text-content-type})) + +(def move-to-internal-failure-message + (console-message {:message-id chat-const/move-to-internal-failure-message-id + :content {:command "grant-permissions" + :content (i18n/label :t/move-to-internal-failure-message)} + :content-type const/content-type-command-request})) + +(defn passphrase-messages [mnemonic signing-phrase crazy-math-message?] + [(console-message {:message-id chat-const/passphrase-message-id + :content (if crazy-math-message? + (i18n/label :t/phew-here-is-your-passphrase) + (i18n/label :t/here-is-your-passphrase)) + :content-type const/text-content-type}) + + (console-message {:message-id (random/id) + :content mnemonic + :content-type const/text-content-type}) + + (console-message {:message-id chat-const/signing-phrase-message-id + :content (i18n/label :t/here-is-your-signing-phrase) + :content-type const/text-content-type}) + + (console-message {:message-id (random/id) + :content signing-phrase + :content-type const/text-content-type})]) + +(def intro-status-message + (console-message {:message-id chat-const/intro-status-message-id + :content (i18n/label :t/intro-status) + :content-type const/content-type-status})) + +(def intro-message1 + (console-message {:message-id chat-const/intro-message1-id + :content {:command "password" + :content (i18n/label :t/intro-message1)} + :content-type const/content-type-command-request})) + +(def chat + {:chat-id const/console-chat-id + :name (string/capitalize const/console-chat-id) + :color default-chat-color + :group-chat false + :is-active true + :unremovable? true + :timestamp (.getTime (js/Date.)) + :photo-path const/console-chat-id + :contacts [{:identity const/console-chat-id + :text-color "#FFFFFF" + :background-color "#AB7967"}]}) + +(def contact + {:whisper-identity const/console-chat-id + :name (string/capitalize const/console-chat-id) + :photo-path const/console-chat-id + :dapp? true + :unremovable? true + :bot-url "local://console-bot" + :status (i18n/label :t/intro-status)}) diff --git a/src/status_im/chat/events.cljs b/src/status_im/chat/events.cljs index 5639d23823..4549385320 100644 --- a/src/status_im/chat/events.cljs +++ b/src/status_im/chat/events.cljs @@ -5,11 +5,14 @@ [status-im.utils.gfycat.core :as gfycat] [status-im.chat.models :as model] [status-im.chat.models.unviewed-messages :as unviewed-messages-model] - [status-im.chat.sign-up :as sign-up] + [status-im.chat.console :as console-chat] [status-im.chat.constants :as chat-const] [status-im.data-store.messages :as msg-store] [status-im.data-store.contacts :as contacts-store] [status-im.data-store.chats :as chats-store] + [status-im.data-store.contacts :as contacts-store] + [status-im.data-store.requests :as requests-store] + [status-im.data-store.messages :as messages-store] [status-im.ui.screens.navigation :as navigation] [status-im.protocol.core :as protocol] [status-im.constants :as const] @@ -28,17 +31,17 @@ (re-frame/reg-cofx :stored-unviewed-messages (fn [cofx _] - (assoc cofx :stored-unviewed-messages (msg-store/get-unviewed)))) + (assoc cofx :stored-unviewed-messages (messages-store/get-unviewed)))) (re-frame/reg-cofx :get-stored-message (fn [cofx _] - (assoc cofx :get-stored-message msg-store/get-by-id))) + (assoc cofx :get-stored-message messages-store/get-by-id))) (re-frame/reg-cofx :get-stored-messages (fn [cofx _] - (assoc cofx :get-stored-messages msg-store/get-by-chat-id))) + (assoc cofx :get-stored-messages messages-store/get-by-chat-id))) (re-frame/reg-cofx :all-stored-chats @@ -50,17 +53,18 @@ (fn [cofx _] (assoc cofx :get-stored-chat chats-store/get-by-id))) + ;;;; Effects (re-frame/reg-fx :update-message (fn [message] - (msg-store/update-message message))) + (messages-store/update-message message))) (re-frame/reg-fx :save-message - (fn [{:keys [chat-id] :as message}] - (msg-store/save chat-id message))) + (fn [message] + (messages-store/save message))) (re-frame/reg-fx :save-chat @@ -107,8 +111,8 @@ [re-frame/trim-v] (fn [db [details]] (model/set-chat-ui-props db {:show-bottom-info? true - :show-emoji? false - :bottom-info details}))) + :show-emoji? false + :bottom-info details}))) (def index-messages (partial into {} (map (juxt :message-id identity)))) @@ -136,13 +140,14 @@ {:db db} (cond-> {:db (-> db (assoc :current-chat-id const/console-chat-id) - (update :chats assoc const/console-chat-id sign-up/console-chat)) - :dispatch-n [[:add-contacts [sign-up/console-contact]]] - :save-chat sign-up/console-chat - :save-all-contacts [sign-up/console-contact]} + (update :chats assoc const/console-chat-id console-chat/chat)) + :dispatch-n [[:add-contacts [console-chat/contact]]] + :save-chat console-chat/chat + :save-all-contacts [console-chat/contact]} (not current-account-id) - (update :dispatch-n conj sign-up/intro-event)))) + (update :dispatch-n concat [[:chat-received-message/add-when-commands-loaded console-chat/intro-message1]])))) + (handlers/register-handler-fx :init-console-chat @@ -171,11 +176,10 @@ {} stored-unanswered-requests) chats (reduce (fn [acc {:keys [chat-id] :as chat}] - (assoc acc chat-id - (assoc chat - :unviewed-messages (get chat->unviewed-messages chat-id) - :requests (get chat->message-id->request chat-id) - :messages (index-messages (get-stored-messages chat-id))))) + (assoc acc chat-id (assoc chat + :unviewed-messages (get chat->unviewed-messages chat-id) + :requests (get chat->message-id->request chat-id) + :messages (index-messages (get-stored-messages chat-id))))) {} all-stored-chats)] (-> db @@ -208,24 +212,24 @@ :show-mnemonic [(re-frame/inject-cofx :get-stored-message) re-frame/trim-v] (fn [{:keys [get-stored-message]} [mnemonic signing-phrase]] - (let [crazy-math-message? (get-stored-message chat-const/crazy-math-message-id)] - {:dispatch-n (sign-up/passphrase-messages-events mnemonic - signing-phrase - crazy-math-message?)}))) + (let [crazy-math-message? (get-stored-message chat-const/crazy-math-message-id) + messages-events (->> (console-chat/passphrase-messages mnemonic signing-phrase crazy-math-message?) + (mapv #(vector :chat-received-message/add %)))] + {:dispatch-n messages-events}))) (handlers/register-handler-fx :account-generation-message [(re-frame/inject-cofx :get-stored-message)] (fn [{:keys [get-stored-message]} _] (when-not (get-stored-message chat-const/passphrase-message-id) - {:dispatch sign-up/account-generation-event}))) + {:dispatch [:chat-received-message/add console-chat/account-generation-message]}))) (handlers/register-handler-fx :move-to-internal-failure-message [(re-frame/inject-cofx :get-stored-message)] (fn [{:keys [get-stored-message]} _] (when-not (get-stored-message chat-const/move-to-internal-failure-message-id) - {:dispatch sign-up/move-to-internal-failure-event}))) + {:dispatch [:chat-received-message/add console-chat/move-to-internal-failure-message]}))) (handlers/register-handler-fx :browse-link-from-message diff --git a/src/status_im/chat/events/console.cljs b/src/status_im/chat/events/console.cljs index 44a4ae28a0..30b87a2c53 100644 --- a/src/status_im/chat/events/console.cljs +++ b/src/status_im/chat/events/console.cljs @@ -3,6 +3,7 @@ [status-im.utils.handlers :as handlers] [status-im.constants :as const] [status-im.i18n :as i18n] + [status-im.chat.console :as console-chat] [status-im.chat.events.sign-up :as sign-up-events] [status-im.ui.screens.accounts.events :as accounts-events] [taoensso.timbre :as log] @@ -12,7 +13,7 @@ ;;;; Helper fns -(defn console-respond-command-events +(defn console-respond-command-messages [command random-id-seq] (let [{:keys [command handler-data]} command] (when command @@ -21,38 +22,26 @@ "js" (let [{:keys [err data messages]} handler-data content (or err data) message-events (mapv (fn [{:keys [message type]} id] - [:received-message - {:message-id id - :content (str type ": " message) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) + (console-chat/console-message + {:message-id id + :content (str type ": " message) + :content-type const/text-content-type})) messages random-id-seq)] (conj message-events - [:received-message + (console-chat/console-message {:message-id (first random-id-seq) :content (str content) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}])) + :content-type const/text-content-type}))) (log/debug "ignoring command: " name)))))) (defn faucet-base-url->url [url] (str url "/donate/0x%s")) (defn- faucet-response-event [message-id content] - [:received-message - {:message-id message-id - :content content - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) + [:chat-received-message/add + (console-chat/console-message {:message-id message-id + :content content + :content-type const/text-content-type})]) (def console-commands->fx {"password" @@ -60,7 +49,7 @@ (accounts-events/create-account db (:password params))) "phone" - (fn [{:keys [db]} {:keys [params id]}] + (fn [{:keys [db]} {:keys [params id]}] (sign-up-events/sign-up db (:phone params) id)) "confirmation-code" @@ -71,34 +60,31 @@ (fn [{:keys [db random-id]} {:keys [params id]}] (let [{:accounts/keys [accounts current-account-id]} db current-address (get-in accounts [current-account-id :address]) - faucet-url (faucet-base-url->url (:url params))] - {:http-get {:url (gstring/format faucet-url current-address) + faucet-url (faucet-base-url->url (:url params))] + {:http-get {:url (gstring/format faucet-url current-address) :success-event-creator (fn [_] (faucet-response-event - random-id - (i18n/label :t/faucet-success))) + random-id + (i18n/label :t/faucet-success))) :failure-event-creator (fn [event] (log/error "Faucet error" event) (faucet-response-event - random-id - (i18n/label :t/faucet-error)))}})) + random-id + (i18n/label :t/faucet-error)))}})) "debug" (fn [{:keys [db random-id now] :as cofx} {:keys [params id]}] (let [debug? (= "On" (:mode params))] (-> {:db db} - (accounts-events/account-update {:debug? debug? + (accounts-events/account-update {:debug? debug? :last-updated now}) (assoc :dispatch-n (if debug? [[:initialize-debugging {:force-start? true}] - [:received-message - {:message-id random-id - :content (i18n/label :t/debug-enabled) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]] + [:chat-received-message/add + (console-chat/console-message + {:message-id random-id + :content (i18n/label :t/debug-enabled) + :content-type const/text-content-type})]] [[:stop-debugging]])))))}) (def commands-names (set (keys console-commands->fx))) @@ -120,8 +106,9 @@ ;; TODO(janherich) remove this once send-message events are refactored (handlers/register-handler-fx - :console-respond-command - [(re-frame/inject-cofx :random-id-seq) re-frame/trim-v] - (fn [{:keys [random-id-seq]} [command]] - (when-let [events (console-respond-command-events command random-id-seq)] - {:dispatch-n events}))) + :console-respond-command + [(re-frame/inject-cofx :random-id-seq) re-frame/trim-v] + (fn [{:keys [random-id-seq]} [command]] + (when-let [messages (console-respond-command-messages command random-id-seq)] + (let [events (mapv #(vector :chat-received-message/add %) messages)] + {:dispatch-n events})))) diff --git a/src/status_im/chat/events/receive_message.cljs b/src/status_im/chat/events/receive_message.cljs index 639e18368c..1c6e725727 100644 --- a/src/status_im/chat/events/receive_message.cljs +++ b/src/status_im/chat/events/receive_message.cljs @@ -2,17 +2,12 @@ (:require [re-frame.core :as re-frame] [taoensso.timbre :as log] [status-im.utils.handlers :as handlers] - [status-im.utils.random :as random] - [status-im.utils.clocks :as clocks] - [status-im.constants :as const] - [status-im.chat.utils :as chat-utils] - [status-im.chat.models :as model] - [status-im.chat.models.commands :as commands-model] - [status-im.chat.models.unviewed-messages :as unviewed-messages-model] - [status-im.chat.events.commands :as commands-events] - [status-im.chat.events.requests :as requests-events] [status-im.data-store.chats :as chat-store] - [status-im.data-store.messages :as msg-store])) + [status-im.data-store.messages :as messages-store] + [status-im.chat.events.commands :as commands-events] + [status-im.chat.models.message :as message-model])) + +;;;; Coeffects (re-frame/reg-cofx :pop-up-chat? @@ -24,88 +19,25 @@ (re-frame/reg-cofx :message-exists? (fn [cofx] - (assoc cofx :message-exists? msg-store/exists?))) + (assoc cofx :message-exists? messages-store/exists?))) (re-frame/reg-cofx - :get-last-clock-value - (fn [cofx] - (assoc cofx :get-last-clock-value msg-store/get-last-clock-value))) + :get-last-clock-value + (fn [cofx] + (assoc cofx :get-last-clock-value messages-store/get-last-clock-value))) -(defn- get-current-account - [{:accounts/keys [accounts current-account-id]}] - (get accounts current-account-id)) -(defn- lookup-response-ref - [access-scope->commands-responses account chat contacts response-name] - (let [available-commands-responses (commands-model/commands-responses :response - access-scope->commands-responses - account - chat - contacts)] - (:ref (get available-commands-responses response-name)))) +;;;; FX -(defn- add-message-to-db - [db {:keys [message-id] :as message} chat-id] - (-> db - (chat-utils/add-message-to-db chat-id chat-id message (:new? message)) - (unviewed-messages-model/add-unviewed-message chat-id message-id))) - -(defn add-message - [{:keys [db message-exists? pop-up-chat? get-last-clock-value now] :as cofx} - {:keys [from group-id chat-id content-type content message-id timestamp clock-value] - :as message - :or {clock-value 0}}] - (let [{:keys [access-scope->commands-responses] :contacts/keys [contacts]} db - {:keys [public-key] :as current-account} (get-current-account db) - chat-identifier (or group-id chat-id from)] - ;; proceed with adding message if message is not already stored in realm, - ;; it's not from current user (outgoing message) and it's for relevant chat - ;; (either current active chat or new chat not existing yet) - (when (and (not (message-exists? message-id)) - (not= from public-key) - (pop-up-chat? chat-identifier)) - (let [fx (if (get-in db [:chats chat-identifier]) - (model/upsert-chat cofx {:chat-id chat-identifier - :group-chat (boolean group-id)}) - (model/add-chat cofx chat-identifier)) - command-request? (= content-type const/content-type-command-request) - command (:command content) - enriched-message (cond-> (assoc message - :chat-id chat-identifier - :timestamp (or timestamp now) - :show? true - :clock-value (clocks/receive - clock-value - (get-last-clock-value chat-identifier))) - (and command command-request?) - (assoc-in [:content :content-command-ref] - (lookup-response-ref access-scope->commands-responses - current-account - (get-in fx [:db :chats chat-identifier]) - contacts - command)))] - (cond-> (-> fx - (update :db add-message-to-db enriched-message chat-identifier) - (assoc :save-message (dissoc enriched-message :new?))) - command-request? - (requests-events/add-request chat-identifier enriched-message)))))) - -(def ^:private receive-interceptors - [(re-frame/inject-cofx :message-exists?) (re-frame/inject-cofx :pop-up-chat?) - (re-frame/inject-cofx :get-last-clock-value) (re-frame/inject-cofx :get-stored-chat) - re-frame/trim-v]) - -;; we need this internal event without jail checking, otherwise no response for the jail -;; call to generate preview would result to infinite loop of `:received-message` events (handlers/register-handler-fx ::received-message - receive-interceptors + message-model/receive-interceptors (fn [cofx [message]] - (add-message cofx message))) + (message-model/receive cofx message))) (handlers/register-handler-fx - :received-message - receive-interceptors + :chat-received-message/add + message-model/receive-interceptors (fn [{:keys [db] :as cofx} [{:keys [content] :as message}]] (if (:command content) ;; we are dealing with received command message, we can't add it right away, @@ -113,20 +45,20 @@ ;; note that `request-command-message-data` implicitly wait till jail is ready and ;; call is made only after that (commands-events/request-command-message-data - db message - {:data-type :preview - :proceed-event-creator (fn [preview] - [::received-message - (assoc-in message [:content :preview] preview)])}) + db message + {:data-type :preview + :proceed-event-creator (fn [preview] + [::received-message + (assoc-in message [:content :preview] preview)])}) ;; regular non command message, we can add it right away - (add-message cofx message)))) + (message-model/receive cofx message)))) ;; TODO janherich: get rid of this special case once they hacky app start-up sequence is refactored (handlers/register-handler-fx - :received-message-when-commands-loaded - receive-interceptors + :chat-received-message/add-when-commands-loaded + message-model/receive-interceptors (fn [{:keys [db] :as cofx} [{:keys [chat-id] :as message}]] (if (and (:status-node-started? db) (get-in db [:contacts/contacts chat-id :jail-loaded?])) - (add-message cofx message) - {:dispatch-later [{:ms 400 :dispatch [:received-message-when-commands-loaded message]}]}))) + (message-model/receive cofx message) + {:dispatch-later [{:ms 400 :dispatch [:chat-received-message/add-when-commands-loaded message]}]}))) diff --git a/src/status_im/chat/events/sign_up.cljs b/src/status_im/chat/events/sign_up.cljs index 036a8e8537..cadac62a9e 100644 --- a/src/status_im/chat/events/sign_up.cljs +++ b/src/status_im/chat/events/sign_up.cljs @@ -1,7 +1,7 @@ (ns status-im.chat.events.sign-up (:require [re-frame.core :as re-frame] [status-im.constants :as const] - [status-im.chat.sign-up :as sign-up] + [status-im.chat.console :as console-chat] [status-im.utils.handlers :as handlers] [status-im.utils.phone-number :as phone-number-util] [status-im.utils.sms-listener :as sms-listener] @@ -84,7 +84,7 @@ (fn [{:keys [db random-id]} [message-id]] (-> {:db db :dispatch-n [;; create manual way for entering confirmation code - (sign-up/enter-confirmation-code-event random-id) + [:chat-received-message/add console-chat/enter-confirmation-code-message] ;; create automatic way for receiving confirmation code start-listening-confirmation-code-sms-event]} (message-seen message-id)))) @@ -105,44 +105,45 @@ (defn- sign-up-confirmed [{:keys [db] :as fx} now] (let [last-phone-number (extract-last-phone-number (:chats db)) - fx (-> (stop-listening-confirmation-code-sms fx) - (update :dispatch-n conj - [:request-permissions [:read-contacts] - #(re-frame/dispatch [:sync-contacts (fn [contacts] - [::contacts-synced contacts])])]))] + fx (-> (stop-listening-confirmation-code-sms fx) + (update :dispatch-n conj + [:request-permissions [:read-contacts] + #(re-frame/dispatch [:sync-contacts (fn [contacts] + [::contacts-synced contacts])])]))] (cond-> fx - last-phone-number (accounts-events/account-update {:phone last-phone-number - :last-updated now})))) + last-phone-number (accounts-events/account-update {:phone last-phone-number + :last-updated now})))) (handlers/register-handler-fx ::sign-up-confirm-response [re-frame/trim-v (re-frame/inject-cofx :random-id)] (fn [{:keys [db random-id now]} [{:keys [message status]} message-id]] - (cond-> {:db db - :dispatch-n [[:received-message - {:message-id random-id - :content message - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]]} - message-id - (message-seen message-id) + (let [messages (cond-> [] - (= "confirmed" status) - (sign-up-confirmed now) + true + (conj (console-chat/console-message {:content message + :content-type const/text-content-type})) - (= "failed" status) - (update :dispatch-n conj (sign-up/incorrect-confirmation-code-event random-id))))) + (= "failed" status) + (conj console-chat/incorrect-confirmation-code-message))] + + (cond-> {:db db + :dispatch-n (mapv #(vector :chat-received-message/add %) messages)} + + message-id + (message-seen message-id) + + (= "confirmed" status) + (sign-up-confirmed now))))) (handlers/register-handler-fx ::contacts-synced [re-frame/trim-v (re-frame/inject-cofx :random-id)] (fn [{:keys [db random-id now] :as cofx} [contacts]] (-> {:db db} - (accounts-events/account-update {:signed-up? true :last-updated now}) - (assoc :dispatch (sign-up/contacts-synchronised-event random-id))))) + (accounts-events/account-update {:signed-up? true + :last-updated now}) + (assoc :dispatch [:chat-received-message/add console-chat/contacts-synchronised-message])))) (handlers/register-handler-fx ::http-request-failure diff --git a/src/status_im/chat/handlers/send_message.cljs b/src/status_im/chat/handlers/send_message.cljs index 5ce23f8c1f..4f7c2031b8 100644 --- a/src/status_im/chat/handlers/send_message.cljs +++ b/src/status_im/chat/handlers/send_message.cljs @@ -114,14 +114,17 @@ (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! +(register-handler + ::save-command! (u/side-effect! (fn [db [_ chat-id {:keys [command]} hidden-params]] - (let [command (cond-> (-> command + (let [ + command (cond-> (-> command + (assoc :chat-id chat-id) (update-in [:content :params] #(apply dissoc % hidden-params)) (dissoc :to-message :has-handler :raw-input)))] (dispatch [:upsert-chat! {:chat-id chat-id}]) - (messages/save chat-id command))))) + (messages/save command))))) (register-handler ::dispatch-responded-requests! (u/side-effect! @@ -193,26 +196,29 @@ (fn [db [_ {:keys [chat-id message]}]] (cu/add-message-to-db db chat-id chat-id message))) -(register-handler ::save-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 chat-id message)))) + (messages/save message)))) -(register-handler ::send-dapp-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 + {:chat-id chat-id + :function :on-message-send :parameters {:message content} - :context {:data data - :from current-account-id}}))))) + :context {:data data + :from current-account-id}}))))) -(register-handler :received-bot-response +(register-handler + :received-bot-response (u/side-effect! (fn [{:contacts/keys [contacts]} [_ {:keys [chat-id] :as params} {:keys [result bot-id] :as data}]] (let [{:keys [returned context]} result @@ -221,7 +227,7 @@ content (or err text-message)] (when update-db (dispatch [:update-bot-db {:bot bot-id - :db update-db}])) + :db update-db}])) (dispatch [:suggestions-handler (assoc params :bot-id bot-id :result data @@ -231,35 +237,34 @@ (when (or (not= type "debug") js/goog.DEBUG (get-in contacts [chat-id :debug?])) - (dispatch [:received-message - {:message-id (random/id) - :content (str type ": " message) + (dispatch [:chat-received-message/add + {:message-id (random/id) + :content (str type ": " message) :content-type content-type-log-message - :outgoing false - :chat-id chat-id - :from chat-id - :to "me"}])))) + :outgoing false + :chat-id chat-id + :from chat-id + :to "me"}])))) (when content - (dispatch [:received-message - {:message-id (random/id) - :content (str content) + (dispatch [:chat-received-message/add + {:message-id (random/id) + :content (str content) :content-type text-content-type - :outgoing false - :chat-id chat-id - :from chat-id - :to "me"}])))))) + :outgoing false + :chat-id chat-id + :from chat-id + :to "me"}])))))) (defn handle-message-from-bot [{:keys [message chat-id]}] (cond (string? message) - (dispatch [:received-message - {:message-id (random/id) - :content (str message) - :content-type text-content-type - :outgoing false - :chat-id chat-id - :from chat-id - :to "me"}]) + (dispatch [:chat-received-message/add {:message-id (random/id) + :content (str message) + :content-type text-content-type + :outgoing false + :chat-id chat-id + :from chat-id + :to "me"}]) (= "request" (:type message)) (dispatch [:add-request-message! @@ -370,14 +375,15 @@ (protocol/send-message! (assoc-in options [:message :to] chat-id)))))))) -(register-handler :add-request-message! - (u/side-effect! - (fn [_ [_ {:keys [content chat-id]}]] - (dispatch [:received-message - {:message-id (random/id) - :content (assoc content :bot chat-id) - :content-type content-type-command-request - :outgoing false - :chat-id chat-id - :from chat-id - :to "me"}])))) +(register-handler + :add-request-message! + (u/side-effect! + (fn [_ [_ {:keys [content chat-id]}]] + (dispatch [:chat-received-message/add + {:message-id (random/id) + :content (assoc content :bot chat-id) + :content-type content-type-command-request + :outgoing false + :chat-id chat-id + :from chat-id + :to "me"}])))) diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index 405aaa47e2..4fdb4b6154 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -30,9 +30,9 @@ ([{:keys [db] :as cofx} chat-id chat-props] (let [new-chat (create-new-chat cofx chat-id chat-props) existing-chats (:chats db)] - {:db (cond-> db - (not (contains? existing-chats chat-id)) - (update :chats assoc chat-id new-chat)) + {:db (cond-> db + (not (contains? existing-chats chat-id)) + (update :chats assoc chat-id new-chat)) :save-chat new-chat}))) ;; TODO (yenda): there should be an option to update the timestamp @@ -44,8 +44,8 @@ (let [chat (merge (or (get-stored-chat chat-id) (create-new-chat cofx chat-id {})) chat)] - {:db (update-in db [:chats chat-id] merge chat) - :save-chat chat})) + {:db (update-in db [:chats chat-id] merge chat) + :save-chat chat})) ;; TODO (yenda): an upsert is suppose to add the entry if it doesn't ;; exist and update it if it does diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs new file mode 100644 index 0000000000..6f7b444aa3 --- /dev/null +++ b/src/status_im/chat/models/message.cljs @@ -0,0 +1,77 @@ +(ns status-im.chat.models.message + (:require [re-frame.core :as re-frame] + [status-im.utils.clocks :as clocks] + [status-im.constants :as constants] + [status-im.chat.utils :as chat-utils] + [status-im.chat.models :as chat-model] + [status-im.chat.models.commands :as commands-model] + [status-im.chat.models.unviewed-messages :as unviewed-messages-model] + [status-im.chat.events.requests :as requests-events] + [taoensso.timbre :as log])) + +(defn- get-current-account + [{:accounts/keys [accounts current-account-id]}] + (get accounts current-account-id)) + +(def receive-interceptors + [(re-frame/inject-cofx :message-exists?) + (re-frame/inject-cofx :pop-up-chat?) + (re-frame/inject-cofx :get-last-clock-value) + (re-frame/inject-cofx :random-id) + (re-frame/inject-cofx :get-stored-chat) + re-frame/trim-v]) + +(defn- lookup-response-ref + [access-scope->commands-responses account chat contacts response-name] + (let [available-commands-responses (commands-model/commands-responses :response + access-scope->commands-responses + account + chat + contacts)] + (:ref (get available-commands-responses response-name)))) + +(defn- add-message-to-db + [db {:keys [message-id] :as message} chat-id] + (-> db + (chat-utils/add-message-to-db chat-id chat-id message (:new? message)) + (unviewed-messages-model/add-unviewed-message chat-id message-id))) + +(defn receive + [{:keys [db message-exists? pop-up-chat? get-last-clock-value now] :as cofx} + {:keys [from group-id chat-id content-type content message-id timestamp clock-value] + :as message + :or {clock-value 0}}] + (let [{:keys [access-scope->commands-responses] :contacts/keys [contacts]} db + {:keys [public-key] :as current-account} (get-current-account db) + chat-identifier (or group-id chat-id from)] + ;; proceed with adding message if message is not already stored in realm, + ;; it's not from current user (outgoing message) and it's for relevant chat + ;; (either current active chat or new chat not existing yet) + (when (and (not (message-exists? message-id)) + (not= from public-key) + (pop-up-chat? chat-identifier)) + (let [fx (if (get-in db [:chats chat-identifier]) + (chat-model/upsert-chat cofx {:chat-id chat-identifier + :group-chat (boolean group-id)}) + (chat-model/add-chat cofx chat-identifier)) + command-request? (= content-type constants/content-type-command-request) + command (:command content) + enriched-message (cond-> (assoc message + :chat-id chat-identifier + :timestamp (or timestamp now) + :show? true + :clock-value (clocks/receive + clock-value + (get-last-clock-value chat-identifier))) + (and command command-request?) + (assoc-in [:content :content-command-ref] + (lookup-response-ref access-scope->commands-responses + current-account + (get-in fx [:db :chats chat-identifier]) + contacts + command)))] + (cond-> (-> fx + (update :db add-message-to-db enriched-message chat-identifier) + (assoc :save-message (dissoc enriched-message :new?))) + command-request? + (requests-events/add-request chat-identifier enriched-message)))))) \ No newline at end of file diff --git a/src/status_im/chat/sign_up.cljs b/src/status_im/chat/sign_up.cljs deleted file mode 100644 index efb7bd6157..0000000000 --- a/src/status_im/chat/sign_up.cljs +++ /dev/null @@ -1,154 +0,0 @@ -(ns status-im.chat.sign-up - (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] - [status-im.ui.components.styles :refer [default-chat-color]] - [status-im.utils.random :as random] - [status-im.constants :as const] - [status-im.chat.constants :as chat-const] - [status-im.i18n :refer [label]] - [clojure.string :as s])) - -(defn send-console-message [text] - {:message-id (random/id) - :from "me" - :to const/console-chat-id - :content text - :content-type const/text-content-type - :outgoing true}) - -;; -- Send phone number ---------------------------------------- -(defn- confirmation-code-event [correct? message-id] - [:received-message - {:message-id message-id - :content {:command "confirmation-code" - :content (if correct? - (label :t/confirmation-code) - (label :t/incorrect-code))} - :content-type const/content-type-command-request - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) - -(def enter-confirmation-code-event (partial confirmation-code-event true)) -(def incorrect-confirmation-code-event (partial confirmation-code-event false)) - -;; -- Send confirmation code and synchronize contacts--------------------------- -(defn contacts-synchronised-event [message-id] - [:received-message - {:message-id message-id - :content (label :t/contacts-syncronized) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) - -(def start-signup-events - [[:received-message - {:message-id (random/id) - :content {:command "phone" - :content (label :t/phone-number-required)} - :content-type const/content-type-command-request - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}] - [:received-message - {:message-id (random/id) - :content (label :t/shake-your-phone) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]]) - -;; -- Saving password ---------------------------------------- -(def account-generation-event - [:received-message - {:message-id chat-const/crazy-math-message-id - :content (label :t/account-generation-message) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) - -(def move-to-internal-failure-event - [:received-message - {:message-id chat-const/move-to-internal-failure-message-id - :content {:command "grant-permissions" - :content (label :t/move-to-internal-failure-message)} - :content-type const/content-type-command-request - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]) - -(defn passphrase-messages-events [mnemonic signing-phrase crazy-math-message?] - [[:received-message - {:message-id chat-const/passphrase-message-id - :content (if crazy-math-message? - (label :t/phew-here-is-your-passphrase) - (label :t/here-is-your-passphrase)) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}] - [:received-message - {:message-id (random/id) - :content mnemonic - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}] - [:received-message - {:message-id chat-const/signing-phrase-message-id - :content (label :t/here-is-your-signing-phrase) - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}] - [:received-message - {:message-id (random/id) - :content signing-phrase - :content-type const/text-content-type - :outgoing false - :chat-id const/console-chat-id - :from const/console-chat-id - :to "me"}]]) - -(def intro-event - [:received-message-when-commands-loaded - {:chat-id const/console-chat-id - :message-id chat-const/intro-message1-id - :content {:command "password" - :content (label :t/intro-message1)} - :content-type const/content-type-command-request - :outgoing false - :from const/console-chat-id - :to "me"}]) - -(def console-chat - {:chat-id const/console-chat-id - :name (s/capitalize const/console-chat-id) - :color default-chat-color - :group-chat false - :is-active true - :unremovable? true - :timestamp (.getTime (js/Date.)) - :photo-path const/console-chat-id - :contacts [{:identity const/console-chat-id - :text-color "#FFFFFF" - :background-color "#AB7967"}]}) - -(def console-contact - {:whisper-identity const/console-chat-id - :name (s/capitalize const/console-chat-id) - :photo-path const/console-chat-id - :dapp? true - :unremovable? true - :bot-url "local://console-bot" - :status (label :t/intro-status)}) diff --git a/src/status_im/chat/views/api/geolocation/views.cljs b/src/status_im/chat/views/api/geolocation/views.cljs index 27f3a0a4e0..a6f0eff358 100644 --- a/src/status_im/chat/views/api/geolocation/views.cljs +++ b/src/status_im/chat/views/api/geolocation/views.cljs @@ -88,8 +88,8 @@ [view st/location-container [text {:style st/location-container-title} (label :t/your-current-location)] - (let [{:keys [place_name center] :as feature} (get-in @cur-loc-geocoded [:features 0])] - [place-item {:title (:text feature) :address place_name :center center}])])))}))) + (let [{:keys [place_name center] :as feature} (get-in @cur-loc-geocoded [:features 0])] + [place-item {:title (:text feature) :address place_name :center center}])])))}))) (defn places-nearby-view [] (let [geolocation (subscribe [:get :geolocation]) diff --git a/src/status_im/data_store/messages.cljs b/src/status_im/data_store/messages.cljs index 6f0c287c79..fedff15906 100644 --- a/src/status_im/data_store/messages.cljs +++ b/src/status_im/data_store/messages.cljs @@ -72,14 +72,12 @@ (update content :params dissoc :password :password-confirmation)))) (defn save - ;; todo remove chat-id parameter - [chat-id {:keys [message-id content] :as message}] + [{:keys [message-id content] :as message}] (when-not (data-store/exists? message-id) (let [content' (prepare-content content) message' (merge default-values message - {:chat-id chat-id - :content content' + {:content content' :timestamp (random/timestamp)})] (data-store/save message')))) diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index eae440cc74..3929e65b80 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -137,7 +137,7 @@ (string/join " ") (system-message message-id timestamp)) message' (assoc message :group-id group-id)] - (re-frame/dispatch [:received-message message'])))) + (re-frame/dispatch [:chat-received-message/add message'])))) (re-frame/reg-fx ::chats-add-contact @@ -164,7 +164,7 @@ (string/join " ") (system-message message-id timestamp)) message' (assoc message :group-id group-id)] - (re-frame/dispatch [:received-message message'])))) + (re-frame/dispatch [:chat-received-message/add message'])))) (re-frame/reg-fx ::stop-watching-group! @@ -174,10 +174,11 @@ (re-frame/reg-fx ::participant-left-group-message (fn [{:keys [chat-id from message-id timestamp]}] - (let [left-name (:name (contacts/get-by-id from))] - (->> (str (or left-name from) " " (i18n/label :t/left)) - (system-message message-id timestamp) - (messages/save chat-id))))) + (let [left-name (:name (contacts/get-by-id from)) + message-text (str (or left-name from) " " (i18n/label :t/left))] + (-> (system-message message-id timestamp message-text) + (assoc :chat-id chat-id) + (messages/save))))) (re-frame/reg-fx ::participant-invited-to-group-message @@ -187,12 +188,12 @@ (i18n/label :t/You) (:name (contacts/get-by-id identity)))] (re-frame/dispatch - [:received-message - {:from "system" - :group-id chat-id - :timestamp timestamp - :message-id message-id - :content (str (or inviter-name from) " " (i18n/label :t/invited) " " (or invitee-name identity)) + [:chat-received-message/add + {:from "system" + :group-id chat-id + :timestamp timestamp + :message-id message-id + :content (str (or inviter-name from) " " (i18n/label :t/invited) " " (or invitee-name identity)) :content-type constants/text-content-type}])))) (re-frame/reg-fx @@ -201,16 +202,16 @@ (let [message-id' (or ack-of-message message-id)] (when-let [{:keys [message-status] :as message} (messages/get-by-id message-id')] (when-not (= (keyword message-status) :seen) - (let [group? (boolean group-id) + (let [group? (boolean group-id) message' (-> (if (and group? (not= status :sent)) (update-in message [:user-statuses from] (fn [{old-status :status}] - {:id (random/id) + {:id (random/id) :whisper-identity from - :status (if (= (keyword old-status) :seen) - old-status - status)})) + :status (if (= (keyword old-status) :seen) + old-status + status)})) (assoc message :message-status status)) ;; we need to dissoc preview because it has been saved before (dissoc :preview))] @@ -227,7 +228,7 @@ (pending-messages/save pending-message) (when (#{:message :group-message} type) (messages/update-message {:message-id id - :delivery-status :pending})))) + :delivery-status :pending})))) (re-frame/reg-fx ::status-init-jail @@ -326,7 +327,7 @@ route-event (case type (:message :group-message - :public-group-message) [:received-message (transform-protocol-message message)] + :public-group-message) [:chat-received-message/add (transform-protocol-message message)] :ack (if (#{:message :group-message} (:type payload)) [:update-message-status message :delivered] [:pending-message-remove message]) @@ -357,7 +358,7 @@ (when route-event {:dispatch route-event}))))))) (defn update-message-status [db {:keys [message-id ack-of-message group-id from status]}] - (let [message-id' (or ack-of-message message-id) + (let [message-id' (or ack-of-message message-id) update-group-status? (and group-id (not= status :sent)) message-path [:chats (or group-id from) :messages message-id'] current-status (if update-group-status? diff --git a/src/status_im/ui/screens/accounts/login/events.cljs b/src/status_im/ui/screens/accounts/login/events.cljs index 55148879f7..c8057d93cf 100644 --- a/src/status_im/ui/screens/accounts/login/events.cljs +++ b/src/status_im/ui/screens/accounts/login/events.cljs @@ -3,7 +3,7 @@ [re-frame.core :refer [dispatch reg-fx]] [status-im.utils.handlers :refer [register-handler-db register-handler-fx]] [taoensso.timbre :as log] - [status-im.chat.sign-up :as sign-up] + [status-im.chat.console :as console-chat] [status-im.utils.types :refer [json->clj]] [status-im.data-store.core :as data-store] [status-im.native-module.core :as status] @@ -126,9 +126,11 @@ (if (nil? error) {:db (dissoc db :accounts/login) :dispatch-n [[:stop-debugging] - [:initialize-account address (when (or new-account? - recover-in-progress?) - sign-up/start-signup-events)] + [:initialize-account + address + (when (or new-account? recover-in-progress?) + [[:chat-received-message/add console-chat/phone-number-request-message] + [:chat-received-message/add console-chat/shake-your-phone-message]])] [:navigate-to-clean :chat-list] (if new-account? [:navigate-to-chat console-chat-id] diff --git a/src/status_im/ui/screens/contacts/events.cljs b/src/status_im/ui/screens/contacts/events.cljs index 2544e0bee1..dfec9386dc 100644 --- a/src/status_im/ui/screens/contacts/events.cljs +++ b/src/status_im/ui/screens/contacts/events.cljs @@ -17,7 +17,7 @@ [status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.i18n :refer [label]] [status-im.ui.screens.contacts.navigation] - [status-im.chat.sign-up :as sign-up] + [status-im.chat.console :as console-chat] [status-im.commands.events.loading :as loading-events] [cljs.spec.alpha :as spec])) @@ -234,7 +234,7 @@ :bot-url bot-url :description description :dapp-hash dapp-hash}) - all-default-contacts (conj default-contacts sign-up/console-contact)] + all-default-contacts (conj default-contacts console-chat/contact)] [[:add-contacts all-default-contacts]])) (defn- prepare-add-chat-events [contacts default-contacts] diff --git a/src/status_im/ui/screens/group/chat_settings/events.cljs b/src/status_im/ui/screens/group/chat_settings/events.cljs index c5d8446238..fa6d9ad9e2 100644 --- a/src/status_im/ui/screens/group/chat_settings/events.cljs +++ b/src/status_im/ui/screens/group/chat_settings/events.cljs @@ -35,10 +35,11 @@ :content-type text-content-type}) (defn removed-participant-message [chat-id identity] - (let [contact-name (:name (contacts/get-by-id identity))] - (->> (str "You've removed " (or contact-name identity)) - (system-message (random/id)) - (messages/save chat-id)))) + (let [contact-name (:name (contacts/get-by-id identity)) + message-text (str "You've removed " (or contact-name identity))] + (-> (system-message (random/id) message-text) + (assoc :chat-id chat-id) + (messages/save)))) (reg-fx ::create-removing-messages