diff --git a/src/status_im/chat/core.cljs b/src/status_im/chat/core.cljs index 8719d4b7b3..5522e353e1 100644 --- a/src/status_im/chat/core.cljs +++ b/src/status_im/chat/core.cljs @@ -5,21 +5,20 @@ ;; Seen messages (fx/defn receive-seen [{:keys [db js-obj]} chat-id sender {:keys [message-ids]}] - (merge {:transport/confirm-messages-processed [{:web3 (:web3 db) - :js-obj js-obj}]} - (when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages]) - (select-keys message-ids) - keys)] - (let [statuses (map (fn [message-id] - {:chat-id chat-id - :message-id message-id - :public-key sender - :status :seen}) - seen-messages-ids)] - {:db (reduce (fn [acc {:keys [message-id] :as status}] - (assoc-in acc [:chats chat-id :message-statuses - message-id sender] - status)) - db - statuses) - :data-store/tx [(user-statuses-store/save-statuses-tx statuses)]})))) + (when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages]) + (select-keys message-ids) + keys)] + (let [statuses (map (fn [message-id] + {:chat-id chat-id + :message-id message-id + :public-key sender + :status :seen}) + seen-messages-ids)] + {:db (reduce (fn [acc {:keys [message-id] :as status}] + (assoc-in acc [:chats chat-id :message-statuses + message-id sender] + status)) + db + statuses) + :data-store/tx [{:transaction (user-statuses-store/save-statuses-tx statuses) + :success-event [:message/message-persisted js-obj]}]}))) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 3812064057..f17c0c8253 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -111,7 +111,7 @@ (fx/defn add-message [{:keys [db] :as cofx} {{:keys [chat-id message-id clock-value timestamp from] :as message} :message - :keys [current-chat? batch? last-clock-value]}] + :keys [current-chat? batch? last-clock-value raw-message]}] (let [current-public-key (accounts.db/current-public-key cofx) prepared-message (-> message (prepare-message chat-id current-chat?) @@ -136,7 +136,10 @@ (not= from current-public-key)) (update-in [:chats chat-id :loaded-unviewed-messages-ids] (fnil conj #{}) message-id)) - :data-store/tx [(messages-store/save-message-tx prepared-message)]} + :data-store/tx [(merge + {:transaction (messages-store/save-message-tx prepared-message)} + (when raw-message + {:success-event [:message/message-persisted raw-message]}))]} (when (and platform/desktop? (not batch?) (not (system-message? prepared-message))) @@ -196,11 +199,10 @@ ;; TODO (cammellos): Refactor so it's not computed twice (add-outgoing-status current-public-key))] (fx/merge cofx - {:transport/confirm-messages-processed [{:web3 web3 - :js-obj js-obj}]} (add-message {:batch? true :message message - :current-chat current-chat?}) + :current-chat current-chat? + :raw-message js-obj}) ;; Checking :outgoing here only works for now as we don't have a :seen ;; status for public chats, if we add processing of our own messages ;; for 1-to-1 care needs to be taken not to override the :seen status @@ -468,6 +470,11 @@ [{:keys [db]} chat-id message-id] {:db (update-in db [:chats chat-id :messages message-id :expanded?] not)}) +(fx/defn confirm-message-processed + [{:keys [db]} raw-message] + {:transport/confirm-messages-processed [{:web3 (:web3 db) + :js-obj raw-message}]}) + ;; effects (re-frame.core/reg-fx diff --git a/src/status_im/data_store/core.cljs b/src/status_im/data_store/core.cljs index 325e0c3f2b..790b9e8911 100644 --- a/src/status_im/data_store/core.cljs +++ b/src/status_im/data_store/core.cljs @@ -46,14 +46,37 @@ (then #(data-source/open-account address password encryption-key)))) +(defn merge-events-of-type [success-events event-type] + ;; merges data value of events of specified type together + ;; keeps the other events intact + ;; [[:e1 [:d1]] [:e1 [:d2]]] => [[:e1 [:d1 :d2]]] + (let [event-to-merge? (fn [event] + (and (vector? event) + (= (first event) event-type) + (vector? (second event)))) + unmergeable-events (filter (complement event-to-merge?) success-events) + mergeable-events (filter event-to-merge? success-events)] + (into [] + (into unmergeable-events + (when-not (empty? mergeable-events) + (let [merged-values (reduce into + (map second mergeable-events))] + [(into [event-type] + (when merged-values + [merged-values]))])))))) + +(defn- merge-persistence-events [success-events] + (merge-events-of-type success-events :message/message-persisted)) + (defn- perform-transactions [raw-transactions realm] (let [success-events (keep :success-event raw-transactions) transactions (map (fn [{:keys [transaction] :as f}] (or transaction f)) raw-transactions)] (data-source/write realm #(doseq [transaction transactions] (transaction realm))) - (doseq [event success-events] - (re-frame/dispatch event)))) + (let [optimized-events (merge-persistence-events success-events)] + (doseq [event optimized-events] + (re-frame/dispatch event))))) (re-frame/reg-fx :data-store/base-tx diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 5730153959..a60cd0698d 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -788,6 +788,11 @@ (fn [cofx [_ chat-id message-id status]] (chat.message/update-message-status cofx chat-id message-id status))) +(handlers/register-handler-fx + :message/message-persisted + (fn [cofx [_ raw-message]] + (chat.message/confirm-message-processed cofx raw-message))) + ;; signal module (handlers/register-handler-fx diff --git a/src/status_im/transport/message/core.cljs b/src/status_im/transport/message/core.cljs index 3ba3b7d603..791b5e792e 100644 --- a/src/status_im/transport/message/core.cljs +++ b/src/status_im/transport/message/core.cljs @@ -150,7 +150,6 @@ (apply fx/merge cofx resend-contact-message-fxs)))) (re-frame/reg-fx - ;; TODO(janherich): this should be called after `:data-store/tx` actually :transport/confirm-messages-processed (fn [messages] (let [{:keys [web3]} (first messages) diff --git a/test/cljs/status_im/test/chat/models/message.cljs b/test/cljs/status_im/test/chat/models/message.cljs index 0a5572ba43..f30c27fecf 100644 --- a/test/cljs/status_im/test/chat/models/message.cljs +++ b/test/cljs/status_im/test/chat/models/message.cljs @@ -56,8 +56,6 @@ (is message)) (testing "it marks the message as outgoing" (is (= true (:outgoing message)))) - (testing "it confirm the message as processed" - (is (:transport/confirm-messages-processed actual))) (testing "it stores the message" (is (:data-store/tx actual))) (testing "it does not send a seen confirmation" diff --git a/test/cljs/status_im/test/data_store/core.cljs b/test/cljs/status_im/test/data_store/core.cljs new file mode 100644 index 0000000000..1a8bfdd1e6 --- /dev/null +++ b/test/cljs/status_im/test/data_store/core.cljs @@ -0,0 +1,49 @@ +(ns status-im.test.data-store.core + (:require [cljs.test :refer-macros [deftest is testing use-fixtures]] + [status-im.utils.utils :as utils] + [clojure.string :as string] + [status-im.data-store.core :as core])) + +(deftest merge-events-of-type + (def events-test [[:event1 [:data1]] [:event1 [:data2]] + [:event2 [:data3]] [:event2 [:data4]] + [:event3 [:data5]] + [:event4 :data6] + [:event5]]) + (testing "merging-events-with-data" + (is (= (core/merge-events-of-type events-test :event1) + [[:event1 [:data1 :data2]] + [:event2 [:data3]] [:event2 [:data4]] + [:event3 [:data5]] + [:event4 :data6] + [:event5]])) + + (is (= (core/merge-events-of-type events-test :event2) + [[:event2 [:data3 :data4]] + [:event1 [:data1]] [:event1 [:data2]] + [:event3 [:data5]] + [:event4 :data6] + [:event5]])) + + (is (= (core/merge-events-of-type events-test :event3) + [[:event3 [:data5]] + [:event1 [:data1]] [:event1 [:data2]] + [:event2 [:data3]] [:event2 [:data4]] + [:event4 :data6] + [:event5]])) + + ;; we can't group non-vector event data + (is (= (core/merge-events-of-type events-test :event4) + [[:event1 [:data1]] [:event1 [:data2]] + [:event2 [:data3]] [:event2 [:data4]] + [:event3 [:data5]] + [:event4 :data6] + [:event5]])) + + ;; we can't group non-vector event data + (is (= (core/merge-events-of-type events-test :event5) + [[:event1 [:data1]] [:event1 [:data2]] + [:event2 [:data3]] [:event2 [:data4]] + [:event3 [:data5]] + [:event4 :data6] + [:event5]])))) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index c6505102fd..fc0423232a 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -2,6 +2,7 @@ (:require [doo.runner :refer-macros [doo-tests]] [status-im.test.contacts.db] [status-im.test.data-store.chats] + [status-im.test.data-store.core] [status-im.test.data-store.realm.core] [status-im.test.extensions.core] [status-im.test.extensions.ethereum] @@ -75,6 +76,7 @@ 'status-im.test.chat.models 'status-im.test.init.core 'status-im.test.data-store.chats + 'status-im.test.data-store.core 'status-im.test.data-store.realm.core 'status-im.test.extensions.core 'status-im.test.mailserver.core