From 6fa482a776467b37d200a40af629aa3433eec0ee Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Tue, 30 Jul 2019 19:16:52 +0200 Subject: [PATCH] Move chats to status-go This commit moves chats to status-go. I have changed the logic to load all chats in one go for simplicity and while that might have a performance impact, I think it's premature to optimize this flow as there will be more changes to the login flow. Also currently this is likely to be slower as we need to wait for the status-service to be initialized, as well as realm. No migration is provided as we are past the point of no return, so by installing this version you will lose your chats. Signed-off-by: Andrea Maria Piana --- src/status_im/chat/models.cljs | 34 +-- src/status_im/chat/models/loading.cljs | 51 ++--- src/status_im/contact/block.cljs | 7 +- src/status_im/data_store/chats.cljs | 215 +++++++++--------- src/status_im/data_store/contacts.cljs | 7 +- src/status_im/ethereum/json_rpc.cljs | 5 + src/status_im/events.cljs | 14 +- src/status_im/group_chats/core.cljs | 4 +- src/status_im/multiaccounts/login/core.cljs | 2 + src/status_im/pairing/core.cljs | 9 +- src/status_im/signals/core.cljs | 1 - src/status_im/transport/core.cljs | 1 - src/status_im/transport/message/protocol.cljs | 9 +- .../screens/desktop/main/tabs/home/views.cljs | 5 - .../screens/group/chat_settings/events.cljs | 35 --- src/status_im/ui/screens/home/views.cljs | 3 - src/status_im/utils/pairing.cljs | 11 + status-go-version.json | 6 +- test/cljs/status_im/test/chat/models.cljs | 22 +- .../cljs/status_im/test/data_store/chats.cljs | 170 +++++++++++--- .../cljs/status_im/test/group_chats/core.cljs | 4 +- test/cljs/status_im/test/pairing/core.cljs | 16 +- test/cljs/status_im/test/sign_in/flow.cljs | 5 +- test/cljs/status_im/test/transport/core.cljs | 2 - 24 files changed, 344 insertions(+), 294 deletions(-) create mode 100644 src/status_im/utils/pairing.cljs diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index e2335c6cf1..052a328850 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -101,8 +101,9 @@ (or (get (:chats db) chat-id) (create-new-chat chat-id cofx)) chat-props)] - {:db (update-in db [:chats chat-id] merge chat) - :data-store/tx [(chats-store/save-chat-tx chat)]})) + (fx/merge cofx + {:db (update-in db [:chats chat-id] merge chat)} + (chats-store/save-chat-rpc chat)))) (fx/defn add-public-chat "Adds new public group chat to db & realm" @@ -138,22 +139,25 @@ :clock-value) deleted-at-clock-value (utils.clocks/send 0))] - {:db (update-in db [:chats chat-id] merge - {:messages empty-message-map - :message-groups {} - :last-message-content nil - :last-message-content-type nil - :unviewed-messages-count 0 - :deleted-at-clock-value last-message-clock-value}) - :data-store/tx [(chats-store/clear-history-tx chat-id last-message-clock-value) - (messages-store/delete-chat-messages-tx chat-id)]})) + (fx/merge + cofx + {:db (update-in db [:chats chat-id] merge + {:messages empty-message-map + :message-groups {} + :last-message-content nil + :last-message-content-type nil + :unviewed-messages-count 0 + :deleted-at-clock-value last-message-clock-value}) + :data-store/tx [(messages-store/delete-chat-messages-tx chat-id)]} + #(chats-store/save-chat-rpc % (get-in % [:db :chats chat-id]))))) (fx/defn deactivate-chat [{:keys [db now] :as cofx} chat-id] - {:db (-> db - (assoc-in [:chats chat-id :is-active] false) - (assoc-in [:current-chat-id] nil)) - :data-store/tx [(chats-store/deactivate-chat-tx chat-id now)]}) + (fx/merge cofx + {:db (-> db + (assoc-in [:chats chat-id :is-active] false) + (assoc-in [:current-chat-id] nil))} + #(chats-store/save-chat-rpc % (get-in % [:db :chats chat-id])))) (fx/defn remove-chat "Removes chat completely from app, producing all necessary effects for that" diff --git a/src/status_im/chat/models/loading.cljs b/src/status_im/chat/models/loading.cljs index d5ce17edd1..25f133a4b0 100644 --- a/src/status_im/chat/models/loading.cljs +++ b/src/status_im/chat/models/loading.cljs @@ -1,6 +1,8 @@ (ns status-im.chat.models.loading (:require [re-frame.core :as re-frame] + [status-im.data-store.chats :as data-store.chats] [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] [status-im.mailserver.core :as mailserver] @@ -55,35 +57,7 @@ (fx/defn update-chats-in-app-db {:events [:chats-list/load-success]} - [{:keys [db] :as cofx} chats] - (fx/merge cofx - {:db (assoc db :chats chats)} - (commands/load-commands commands/register))) - -(defn- unkeywordize-chat-names - [chats] - (reduce-kv - (fn [acc chat-keyword chat] - (assoc acc (name chat-keyword) chat)) - {} - chats)) - -(defn load-chats-from-rpc - [cofx] - (fx/merge cofx - {::json-rpc/call [{:method "status_chats" - :params [] - :on-error - #(log/error "can't retrieve chats list from status-go:" %) - :on-success - #(re-frame/dispatch - [:chats-list/load-success - (unkeywordize-chat-names (:chats %))])}]})) - -(defn initialize-chats-legacy - "Use realm + clojure to manage chats" - [{:keys [db get-all-stored-chats] :as cofx} - from to] + [{:keys [db] :as cofx} new-chats] (let [old-chats (:chats db) chats (reduce (fn [acc {:keys [chat-id] :as chat}] (assoc acc chat-id @@ -92,17 +66,26 @@ :referenced-messages {} :messages empty-message-map))) {} - (get-all-stored-chats from to)) + new-chats) chats (merge old-chats chats)] - (update-chats-in-app-db cofx chats))) + (fx/merge cofx + {:db (assoc db :chats chats + :chats/loading? false)} + (filters/load-filters) + (commands/load-commands commands/register)))) +(defn load-chats-from-rpc + [cofx from to] + (data-store.chats/fetch-chats-rpc cofx {:from 0 + :to 10 + :on-success + #(re-frame/dispatch + [:chats-list/load-success %])})) (fx/defn initialize-chats "Initialize persisted chats on startup" [cofx {:keys [from to] :or {from 0 to nil}}] - (if config/use-status-go-protocol? - (load-chats-from-rpc cofx) - (initialize-chats-legacy cofx from to))) + (load-chats-from-rpc cofx from -1)) (defn load-more-messages "Loads more messages for current chat" diff --git a/src/status_im/contact/block.cljs b/src/status_im/contact/block.cljs index 61f85e1084..740e7312a2 100644 --- a/src/status_im/contact/block.cljs +++ b/src/status_im/contact/block.cljs @@ -19,6 +19,8 @@ [{:keys [db] :as cofx} chat-id removed-chat-messages] (let [removed-messages-ids (map :message-id removed-chat-messages) removed-unseen-count (count (remove :seen removed-chat-messages)) + unviewed-messages-count (- (get-in db [:chats chat-id :unviewed-messages-count]) + removed-unseen-count) db (-> db ;; remove messages (update-in [:chats chat-id :messages] @@ -32,8 +34,9 @@ (chat.models/upsert-chat {:chat-id chat-id :unviewed-messages-count - (- (get-in db [:chats chat-id :unviewed-messages-count]) - removed-unseen-count)}) + (if (pos? unviewed-messages-count) + unviewed-messages-count + 0)}) ;; recompute message group (chat.models.loading/group-chat-messages chat-id diff --git a/src/status_im/data_store/chats.cljs b/src/status_im/data_store/chats.cljs index f6a2e8fbbe..cc1638c67c 100644 --- a/src/status_im/data_store/chats.cljs +++ b/src/status_im/data_store/chats.cljs @@ -2,7 +2,9 @@ (:require [goog.object :as object] [re-frame.core :as re-frame] [status-im.data-store.messages :as messages] + [status-im.utils.fx :as fx] [status-im.data-store.realm.core :as core] + [status-im.ethereum.json-rpc :as json-rpc] [status-im.ethereum.core :as ethereum] [taoensso.timbre :as log] [status-im.utils.clocks :as utils.clocks] @@ -16,6 +18,10 @@ (and (coll? v) (empty? v)))) e))) +(def one-to-one-chat-type 1) +(def public-chat-type 2) +(def private-group-chat-type 3) + (defn- event->string "Transform an event in an a vector with keys in alphabetical order, to compute a predictable id" @@ -31,121 +37,124 @@ (defn marshal-membership-updates [updates] (mapcat (fn [{:keys [signature events from]}] - (map #(assoc % - :id (event-id %) - :signature signature - :from from) events)) updates)) + (map #(-> % + (assoc + :clockValue (:clock-value %) + :id (event-id %) + :signature signature + :from from) + (dissoc :clock-value)) events)) updates)) (defn unmarshal-membership-updates [chat-id updates] (->> updates - vals (group-by :signature) (map (fn [[signature events]] - {:events (map #(-> (dissoc % :signature :from :id) + {:events (map #(-> % + (assoc :clock-value (:clockValue %)) + (dissoc :signature :from :id :clockValue) remove-empty-vals) events) :from (-> events first :from) :signature signature :chat-id chat-id})))) -(defn- normalize-chat [{:keys [chat-id] :as chat}] +(defn type->rpc [{:keys [public? group-chat] :as chat}] + (assoc chat :chatType (cond + public? public-chat-type + group-chat private-group-chat-type + :else one-to-one-chat-type))) + +(defn rpc->type [{:keys [chatType] :as chat}] + (cond + (= public-chat-type chatType) (assoc chat :public? true :group-chat true) + (= private-group-chat-type chatType) (assoc chat :public? false :group-chat true) + :else (assoc chat :public? false :group-chat false))) + +(defn- marshal-members [{:keys [admins contacts members-joined chatType] :as chat}] + (cond-> chat + (= chatType private-group-chat-type) + (assoc :members (map #(hash-map :id % + :admin (boolean (admins %)) + :joined (boolean (members-joined %))) contacts)) + :always + (dissoc :admins :contacts :members-joined))) + +(defn- unmarshal-members [{:keys [members chatType] :as chat}] + (cond + (= public-chat-type chatType) (assoc chat + :contacts #{} + :admins #{} + :members-joined #{}) + (= private-group-chat-type chatType) (merge chat + (reduce (fn [acc member] + (cond-> acc + (:admin member) + (update :admins conj (:id member)) + (:joined member) + (update :members-joined conj (:id member)) + :always + (update :contacts conj (:id member)))) + {:admins #{} + :members-joined #{} + :contacts #{}} + members)) + :else + (assoc chat + :contacts #{(:id chat)} + :admins #{} + :members-joined #{}))) + +(defn- ->rpc [chat] (-> chat - (update :admins #(into #{} %)) - (update :contacts #(into #{} %)) - (update :members-joined #(into #{} %)) - (update :tags #(into #{} %)) - (update :membership-updates (partial unmarshal-membership-updates chat-id)) + type->rpc + marshal-members + (update :membership-updates marshal-membership-updates) + (utils/update-if-present :last-message-content messages/prepare-content) + (clojure.set/rename-keys {:chat-id :id + :membership-updates :membershipUpdates + :unviewed-messages-count :unviewedMessagesCount + :last-message-content :lastMessageContent + :last-message-content-type :lastMessageContentType + :deleted-at-clock-value :deletedAtClockValue + :is-active :active + :last-clock-value :lastClockValue}) + (dissoc :referenced-messages :message-groups :gaps-loaded? :pagination-info + :public? :group-chat :messages + :might-have-join-time-messages? + :group-chat-local-version :loaded-unviewed-messages-ids + :messages-initialized? :contacts :admins :members-joined))) + +(defn- <-rpc [chat] + (-> chat + rpc->type + unmarshal-members + (clojure.set/rename-keys {:id :chat-id + :membershipUpdates :membership-updates + :unviewedMessagesCount :unviewed-messages-count + :lastMessageContent :last-message-content + :lastMessageContentType :last-message-content-type + :deletedAtClockValue :deleted-at-clock-value + :active :is-active + :lastClockValue :last-clock-value}) + (update :membership-updates (partial unmarshal-membership-updates (:id chat))) + (update :last-message-content utils/safe-read-message-content) (update :last-clock-value utils.clocks/safe-timestamp) - (update :last-message-content utils/safe-read-message-content))) + (assoc :group-chat-local-version 1) ;; TODO(cammellos): this can be removed + (dissoc :chatType :members))) -(re-frame/reg-cofx - :data-store/all-chats - (fn [cofx _] - (assoc cofx :get-all-stored-chats - (fn [from to] - (map normalize-chat - (-> @core/account-realm - (core/get-all :chat) - (core/sorted :timestamp :desc) - (core/page from to) - (core/all-clj :chat))))))) +(fx/defn save-chat-rpc [cofx {:keys [chat-id] :as chat}] + (json-rpc/call {:method "shhext_saveChat" + :params [(->rpc chat)] + :on-success #(log/debug "saved chat" chat-id "successfuly") + :on-failure #(log/error "failed to save chat" chat-id %)})) -(defn save-chat-tx - "Returns tx function for saving chat" - [chat] - (fn [realm] - (log/debug "saving chat" chat) - (core/create - realm - :chat - (-> chat - (update :membership-updates marshal-membership-updates) - (utils/update-if-present :last-message-content messages/prepare-content)) - true))) +(fx/defn fetch-chats-rpc [cofx {:keys [from to on-success]}] + (json-rpc/call {:method "shhext_chats" + :params [from to] + :on-success #(on-success (map <-rpc %)) + :on-failure #(log/error "failed to fetch chats" from to %)})) -;; Only used in debug mode -(defn delete-chat-tx - "Returns tx function for hard deleting the chat" - [chat-id] - (fn [realm] - (core/delete realm (core/get-by-field realm :chat :chat chat-id)))) - -(defn- get-chat-by-id [chat-id realm] - (.objectForPrimaryKey realm "chat" chat-id)) - -(defn clear-history-tx - "Returns tx function for clearing the history of chat" - [chat-id deleted-at-clock-value] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm)] - (doto chat - (aset "last-message-content" nil) - (aset "last-message-content-type" nil) - (aset "deleted-at-clock-value" deleted-at-clock-value))))) - -(defn deactivate-chat-tx - "Returns tx function for deactivating chat" - [chat-id now] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm)] - (doto chat - (aset "is-active" false))))) - -(defn add-chat-contacts-tx - "Returns tx function for adding chat contacts" - [chat-id contacts] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm) - existing-contacts (object/get chat "contacts")] - (aset chat "contacts" - (clj->js (into #{} (concat contacts - (core/list->clj existing-contacts)))))))) - -(defn remove-chat-contacts-tx - "Returns tx function for removing chat contacts" - [chat-id contacts] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm) - existing-contacts (object/get chat "contacts")] - (aset chat "contacts" - (clj->js (remove (into #{} contacts) - (core/list->clj existing-contacts))))))) - -(defn add-chat-tag-tx - "Returns tx function for adding chat contacts" - [chat-id tag] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm) - existing-tags (object/get chat "tags")] - (aset chat "tags" - (clj->js (into #{} (concat tag - (core/list->clj existing-tags)))))))) - -(defn remove-chat-tag-tx - "Returns tx function for removing chat contacts" - [chat-id tag] - (fn [realm] - (let [chat (get-chat-by-id chat-id realm) - existing-tags (object/get chat "tags")] - (aset chat "tags" - (clj->js (remove (into #{} tag) - (core/list->clj existing-tags))))))) +(defn delete-chat-rpc [chat-id chat-type] + (json-rpc/call {:method "shhext_deleteChat" + :params [chat-id chat-type] + :on-success #(log/debug "deleteed chat" chat-id chat-type) + :on-failure #(log/error "failed to delete chat" chat-id chat-type %)})) diff --git a/src/status_im/data_store/contacts.cljs b/src/status_im/data_store/contacts.cljs index c6e1c149ea..2831bbb783 100644 --- a/src/status_im/data_store/contacts.cljs +++ b/src/status_im/data_store/contacts.cljs @@ -1,5 +1,8 @@ (ns status-im.data-store.contacts (:require [re-frame.core :as re-frame] + [status-im.utils.fx :as fx] + [status-im.data-store.chats :as data-store.chats] + [status-im.ethereum.json-rpc :as json-rpc] [taoensso.timbre :as log] [status-im.data-store.realm.core :as core])) @@ -69,9 +72,7 @@ (when-let [user-messages (get-messages-by-messages-ids messages-ids)] (core/delete realm user-messages)) - (when-let [chat - (get-chat public-key)] - (core/delete realm chat)))) + (data-store.chats/delete-chat-rpc public-key data-store.chats/one-to-one-chat-type))) (defn delete-contact-tx "Returns tx function for deleting contact" diff --git a/src/status_im/ethereum/json_rpc.cljs b/src/status_im/ethereum/json_rpc.cljs index 9febc8b00e..016c619166 100644 --- a/src/status_im/ethereum/json_rpc.cljs +++ b/src/status_im/ethereum/json_rpc.cljs @@ -32,6 +32,11 @@ "shhext_loadFilters" {} "shhext_loadFilter" {} "shhext_removeFilters" {} + "shhext_chats" {} + "shhext_saveChat" {} + "shhext_contacts" {} + "shhext_deleteChat" {} + "shhext_saveContact" {} "status_joinPublicChat" {} "status_chats" {} "status_startOneOnOneChat" {} diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index a309c94fa0..e6f93c1c2b 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -114,16 +114,6 @@ (fn [cofx [_ encryption-key error]] (init/handle-init-store-error cofx encryption-key))) -(handlers/register-handler-fx - :init-rest-of-chats - [(re-frame/inject-cofx :web3/get-web3) - (re-frame/inject-cofx :data-store/all-chats)] - (fn [{:keys [db] :as cofx} [_]] - (log/debug "PERF" :init-rest-of-chats (.now js/Date)) - (fx/merge cofx - {:db (assoc db :chats/loading? false)} - (chat.loading/initialize-chats {:from 10})))) - (defn multiaccount-change-success [{:keys [db] :as cofx} [_ address nodes]] (let [{:node/keys [status]} db] @@ -135,15 +125,13 @@ (multiaccounts.login/login) (node/initialize (get-in db [:multiaccounts/login :address]))) (init/initialize-multiaccount address) - (mailserver/initialize-ranges) - (chat.loading/initialize-chats {:to 10})))) + (mailserver/initialize-ranges)))) (handlers/register-handler-fx :init.callback/multiaccount-change-success [(re-frame/inject-cofx :web3/get-web3) (re-frame/inject-cofx :data-store/get-all-contacts) (re-frame/inject-cofx :data-store/get-all-installations) - (re-frame/inject-cofx :data-store/all-chats) (re-frame/inject-cofx :data-store/all-chat-requests-ranges)] multiaccount-change-success) diff --git a/src/status_im/group_chats/core.cljs b/src/status_im/group_chats/core.cljs index 2aa59a24b3..1ae845cf16 100644 --- a/src/status_im/group_chats/core.cljs +++ b/src/status_im/group_chats/core.cljs @@ -5,7 +5,7 @@ [clojure.string :as string] [re-frame.core :as re-frame] [status-im.multiaccounts.model :as multiaccounts.model] - [status-im.pairing.core :as pairing] + [status-im.utils.pairing :as pairing.utils] [status-im.chat.models :as models.chat] [status-im.chat.models.message :as models.message] [status-im.contact.core :as models.contact] @@ -125,7 +125,7 @@ members-allowed (filter (fn [pk] (if (= pk current-public-key) - (pairing/has-paired-installations? cofx) + (pairing.utils/has-paired-installations? cofx) true)) members) destinations (map (fn [member] diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index c8b40e403a..1ab996449c 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -5,6 +5,7 @@ [status-im.data-store.core :as data-store] [status-im.ethereum.json-rpc :as json-rpc] [status-im.ethereum.subscriptions :as ethereum.subscriptions] + [status-im.chat.models.loading :as chat.loading] [status-im.ethereum.transactions.core :as transactions] [status-im.fleet.core :as fleet] [status-im.i18n :as i18n] @@ -207,6 +208,7 @@ (tribute-to-talk/init) (mobile-network/on-network-status-change) (protocol/initialize-protocol) + (chat.loading/initialize-chats {:to -1}) (universal-links/process-stored-event) (chaos-mode/check-chaos-mode) (finish-keycard-setup) diff --git a/src/status_im/pairing/core.cljs b/src/status_im/pairing/core.cljs index 614e3b5d56..ae9fc55c29 100644 --- a/src/status_im/pairing/core.cljs +++ b/src/status_im/pairing/core.cljs @@ -3,6 +3,7 @@ [clojure.string :as string] [status-im.i18n :as i18n] [status-im.utils.fx :as fx] + [status-im.utils.pairing :as pairing.utils] [status-im.ethereum.json-rpc :as json-rpc] [status-im.contact.device-info :as device-info] [status-im.contact.db :as contact.db] @@ -79,12 +80,6 @@ {:transport/confirm-messages-processed [{:web3 (:web3 db) :js-obj raw-message}]}) -(defn has-paired-installations? [cofx] - (->> - (get-in cofx [:db :pairing/installations]) - vals - (some :enabled?))) - (defn send-pair-installation [cofx payload] (let [{:keys [web3]} (:db cofx) current-public-key (multiaccounts.model/current-public-key cofx)] @@ -303,7 +298,7 @@ :payload payload}]})) (fx/defn send-installation-message-fx [cofx payload] - (when (has-paired-installations? cofx) + (when (pairing.utils/has-paired-installations? cofx) (protocol/send payload nil cofx))) (fx/defn sync-public-chat [cofx chat-id] diff --git a/src/status_im/signals/core.cljs b/src/status_im/signals/core.cljs index e20d205466..9a42bc9c73 100644 --- a/src/status_im/signals/core.cljs +++ b/src/status_im/signals/core.cljs @@ -80,7 +80,6 @@ "discovery.summary" (summary cofx event) "subscriptions.data" (ethereum.subscriptions/handle-signal cofx event) "subscriptions.error" (ethereum.subscriptions/handle-error cofx event) - "status.chats.did-change" (chat.loading/load-chats-from-rpc cofx) "whisper.filter.added" (transport.filters/handle-negotiated-filter cofx event) "messages.new" (transport.message/receive-messages cofx event) "wallet" (ethereum.subscriptions/new-wallet-event cofx event) diff --git a/src/status_im/transport/core.cljs b/src/status_im/transport/core.cljs index 81304e630c..a6895c63b0 100644 --- a/src/status_im/transport/core.cljs +++ b/src/status_im/transport/core.cljs @@ -40,7 +40,6 @@ [{:keys [db web3 all-installations] :as cofx}] (fx/merge cofx (fetch-node-info-fx) - (transport.filters/load-filters) (pairing/init all-installations) (publisher/start-fx) (mailserver/connect-to-mailserver) diff --git a/src/status_im/transport/message/protocol.cljs b/src/status_im/transport/message/protocol.cljs index 881527db6d..36b2692021 100644 --- a/src/status_im/transport/message/protocol.cljs +++ b/src/status_im/transport/message/protocol.cljs @@ -5,6 +5,7 @@ [status-im.constants :as constants] [status-im.ethereum.core :as ethereum] [status-im.transport.db :as transport.db] + [status-im.utils.pairing :as pairing.utils] [status-im.data-store.transport :as transport-store] [status-im.transport.utils :as transport.utils] [status-im.tribute-to-talk.whitelist :as whitelist] @@ -12,12 +13,6 @@ [status-im.utils.fx :as fx] [taoensso.timbre :as log])) -(defn has-paired-installations? [cofx] - (->> - (get-in cofx [:db :pairing/installations]) - vals - (some :enabled?))) - (defn discovery-topic-hash [] (transport.utils/get-topic constants/contact-discovery)) (defprotocol StatusMessage @@ -107,7 +102,7 @@ :user-message (fx/merge cofx - (when (has-paired-installations? cofx) + (when (pairing.utils/has-paired-installations? cofx) (send-direct-message current-public-key nil this)) (send-with-pubkey params))))) (receive [this chat-id signature timestamp cofx] diff --git a/src/status_im/ui/screens/desktop/main/tabs/home/views.cljs b/src/status_im/ui/screens/desktop/main/tabs/home/views.cljs index bccb7f1f39..b42574f4e4 100644 --- a/src/status_im/ui/screens/desktop/main/tabs/home/views.cljs +++ b/src/status_im/ui/screens/desktop/main/tabs/home/views.cljs @@ -150,11 +150,6 @@ (views/letsubs [search-filter [:search/filter] logging-in? [:multiaccounts/login] {:keys [all-home-items chats]} [:home-items]] - {:component-did-mount - (fn [this] - (let [[_ loading?] (.. this -props -argv)] - (when loading? - (re-frame/dispatch [:init-rest-of-chats]))))} [react/view {:style styles/chat-list-view} [react/view {:style styles/chat-list-header} [search-input search-filter] 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 3bfb7fb468..9e94100589 100644 --- a/src/status_im/ui/screens/group/chat_settings/events.cljs +++ b/src/status_im/ui/screens/group/chat_settings/events.cljs @@ -16,38 +16,3 @@ (assoc :current-chat-id chat-id))} (navigation/navigate-to-cofx :group-chat-profile nil)))) -(handlers/register-handler-fx - :add-new-group-chat-participants - [(re-frame/inject-cofx :random-id-generator)] - (fn [{{:keys [current-chat-id selected-participants] :as db} :db - now :now random-id-generator :random-id-generator :as cofx} _] - (let [message-id (random-id-generator) - participants (concat (get-in db [:chats current-chat-id :contacts]) selected-participants) - contacts (:contacts/contacts db) - added-participants-names (map #(get-in contacts [% :name]) selected-participants)] - (fx/merge cofx - {:db (-> db - (assoc-in [:chats current-chat-id :contacts] participants) - (assoc :selected-participants #{})) - :data-store/tx [(chats-store/add-chat-contacts-tx current-chat-id selected-participants)]} - #_(models.message/receive - (models.message/system-message current-chat-id message-id now - (str "You've added " (apply str (interpose ", " added-participants-names))))) - #_(transport/send (protocol/GroupAdminUpdate. nil participants current-chat-id) current-chat-id))))) - -(handlers/register-handler-fx - :remove-group-chat-participants - [(re-frame/inject-cofx :random-id-generator)] - (fn [{{:keys [current-chat-id] :as db} :db now :now random-id-generator :random-id-generator :as cofx} - [_ removed-participants]] - (let [message-id (random-id-generator) - participants (remove removed-participants (get-in db [:chats current-chat-id :contacts])) - contacts (:contacts/contacts db) - removed-participants-names (map #(get-in contacts [% :name]) removed-participants)] - (fx/merge cofx - {:db (assoc-in db [:chats current-chat-id :contacts] participants) - :data-store/tx [(chats-store/remove-chat-contacts-tx current-chat-id removed-participants)]} - #_(models.message/receive - (models.message/system-message current-chat-id message-id now - (str "You've removed " (apply str (interpose ", " removed-participants-names))))) - #_(transport/send (protocol/GroupAdminUpdate. nil participants current-chat-id) current-chat-id))))) diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 7bbc42aea3..e04f52a283 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -126,9 +126,6 @@ {:keys [search-filter chats all-home-items]} [:home-items] window-width [:dimensions/window-width] two-pane-ui-enabled? [:two-pane-ui-enabled?]] - {:component-did-mount (fn [this] - (let [[_ loading?] (.. this -props -argv)] - (when loading? (utils/set-timeout #(re-frame/dispatch [:init-rest-of-chats]) 100))))} (let [home-width (if (> window-width constants/two-pane-min-width) (max constants/left-pane-min-width (/ window-width 3)) window-width)] diff --git a/src/status_im/utils/pairing.cljs b/src/status_im/utils/pairing.cljs new file mode 100644 index 0000000000..1f15310c08 --- /dev/null +++ b/src/status_im/utils/pairing.cljs @@ -0,0 +1,11 @@ +(ns ^{:doc "Pairing utils"} + status-im.utils.pairing) + +(defn has-paired-installations? [cofx] + (let [our-installation-id (get-in cofx [:db :multiaccount :installation-id])] + (->> + (get-in cofx [:db :pairing/installations]) + vals + (some (fn [{:keys [enabled? installation-id]}] + (and (not= installation-id our-installation-id) + enabled?)))))) diff --git a/status-go-version.json b/status-go-version.json index d093588c6f..c88faea4b6 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh ' instead", "owner": "status-im", "repo": "status-go", - "version": "9de77b21b22aeca3c71050ed4f7809f500e63191", - "commit-sha1": "9de77b21b22aeca3c71050ed4f7809f500e63191", - "src-sha256": "1wpyijxqcq1c1ra6vp6sr8zg91r0awpdx5ypgdrvhlnl3mba4k1g" + "version": "a3a413b5d98f227ff541ad9527c8d24e9c9ce653", + "commit-sha1": "a3a413b5d98f227ff541ad9527c8d24e9c9ce653", + "src-sha256": "07sgvpmmjiigga73gymbq1ifm047frmrxn3dr26ihw50p0kp0fwh" } diff --git a/test/cljs/status_im/test/chat/models.cljs b/test/cljs/status_im/test/chat/models.cljs index d5cca0c046..4706ec4a50 100644 --- a/test/cljs/status_im/test/chat/models.cljs +++ b/test/cljs/status_im/test/chat/models.cljs @@ -13,8 +13,7 @@ :db {:contacts/contacts {chat-id {:name contact-name}}}} response (chat/upsert-chat cofx chat-props) - actual-chat (get-in response [:db :chats chat-id]) - store-chat-fx (:data-store/tx response)] + actual-chat (get-in response [:db :chats chat-id])] (testing "it adds the chat to the chats collection" (is actual-chat)) (testing "it adds the extra props" @@ -26,9 +25,7 @@ (testing "it sets the timestamp" (is (= "now" (:timestamp actual-chat)))) (testing "it adds the contact-id to the contact field" - (is (= chat-id (-> actual-chat :contacts first)))) - (testing "it adds the fx to store a chat" - (is store-chat-fx)))) + (is (= chat-id (-> actual-chat :contacts first)))))) (testing "upserting an existing chat" (let [chat-id "some-chat-id" chat-props {:chat-id chat-id @@ -37,24 +34,19 @@ cofx {:db {:chats {chat-id {:is-active true :name "old-name"}}}} response (chat/upsert-chat cofx chat-props) - actual-chat (get-in response [:db :chats chat-id]) - store-chat-fx (:data-store/tx response)] + actual-chat (get-in response [:db :chats chat-id])] (testing "it adds the chat to the chats collection" (is actual-chat)) (testing "it adds the extra props" (is (= "some" (:extra-prop actual-chat)))) (testing "it updates existins props" - (is (= "new-name" (:name actual-chat)))) - (testing "it adds the fx to store a chat" - (is store-chat-fx))))) + (is (= "new-name" (:name actual-chat))))))) (deftest add-public-chat (let [topic "topic" fx (chat/add-public-chat {:db {}} topic) store-fx (:data-store/tx fx) chat (get-in fx [:db :chats topic])] - (testing "it saves the chat in the database" - (is store-fx)) (testing "it sets the name" (is (= topic (:name chat)))) (testing "it sets the participants" @@ -104,7 +96,7 @@ (testing "it adds the relevant transactions for realm" (let [actual (chat/clear-history cofx chat-id)] (is (:data-store/tx actual)) - (is (= 2 (count (:data-store/tx actual)))))))) + (is (= 1 (count (:data-store/tx actual)))))))) (deftest remove-chat-test (let [chat-id "1" @@ -142,7 +134,7 @@ (testing "it adds the relevant transactions for realm" (let [actual (chat/remove-chat cofx chat-id)] (is (:data-store/tx actual)) - (is (= 6 (count (:data-store/tx actual)))))))) + (is (= 4 (count (:data-store/tx actual)))))))) (deftest multi-user-chat? (let [chat-id "1"] @@ -183,7 +175,7 @@ me (get-in test-db [:multiaccount :public-key])] (is (= '(true true true) (map (comp :seen second) (get-in fx [:db :chats "status" :messages])))) - (is (= 2 (count (:data-store/tx fx)))) + (is (= 1 (count (:data-store/tx fx)))) ;; for public chats, no confirmation is sent out (is (= nil (:shh/post fx))))) diff --git a/test/cljs/status_im/test/data_store/chats.cljs b/test/cljs/status_im/test/data_store/chats.cljs index 33a39f32ab..b43a2cea47 100644 --- a/test/cljs/status_im/test/data_store/chats.cljs +++ b/test/cljs/status_im/test/data_store/chats.cljs @@ -3,38 +3,140 @@ [status-im.utils.random :as utils.random] [status-im.data-store.chats :as chats])) +(deftest ->to-rpc + (let [chat {:referenced-messages [] + :public? false + :group-chat true + :message-groups {} + :color "color" + :contacts #{"a" "b" "c" "d"} + :last-clock-value 10 + :admins #{"a" "b"} + :members-joined #{"a" "c"} + :name "name" + :membership-updates [{:chat-id "chat-id" + :from "a" + :signature "b" + :events [{:type "chat-created" + :name "test" + :clock-value 1} + {:type "members-added" + :clock-value 2 + :members ["a" "b"]}]}] + :gaps-loaded? true + :unviewed-messages-count 2 + :is-active true + :messages {} + :pagination-info {} + :last-message-content "content" + :last-message-content-type "type" + :group-chat-local-version 1 + :chat-id "chat-id" + :loaded-unviewed-messages-ids [] + :timestamp 2 + :messages-initialized? true} + expected-chat {:id "chat-id" + :color "color" + :name "name" + :chatType 3 + :lastMessageContent "content" + :lastMessageContentType "type" + :members #{{:id "a" + :admin true + :joined true} + {:id "b" + :admin true + :joined false} + {:id "c" + :admin false + :joined true} + {:id "d" + :admin false + :joined false}} + :lastClockValue 10 + :membershipUpdates #{{:type "chat-created" + :name "test" + :clockValue 1 + :id "0xcdf4a63e0c98d0018cf532b3a48350bb80e292cc46249e3f876aaa65eb97a231" + :signature "b" + :from "a"} + {:type "members-added" + :clockValue 2 + :members ["a" "b"] + :id "0x1c34d6b4d022c432b7eb6b645e095791af0c6bdb626db7d705e6db0d7cd74b56" + :signature "b" + :from "a"}} + :unviewedMessagesCount 2 + :active true + :timestamp 2}] + (testing "marshaling chat" + (is (= expected-chat (-> (chats/->rpc chat) + (update :members #(into #{} %)) + (update :membershipUpdates #(into #{} %)))))))) + (deftest normalize-chat-test - (testing "admins & contacts" - (is (= {:admins #{4} - :contacts #{2} - :tags #{} - :membership-updates [] - :members-joined #{} - :last-message-content {:foo "bar"} - :last-clock-value nil} - (chats/normalize-chat - {:admins [4] - :contacts [2] - :last-message-content "{:foo \"bar\"}"})))) - (testing "membership-updates" - (let [raw-events {"1" {:id "1" :type "members-added" :clock-value 10 :members [1 2] :signature "a" :from "id-1"} - "2" {:id "2" :type "member-removed" :clock-value 11 :member 1 :signature "a" :from "id-1"} - "3" {:id "3" :type "chat-created" :clock-value 0 :name "blah" :signature "b" :from "id-2"}} - expected #{{:chat-id "chat-id" - :from "id-2" - :signature "b" - :events [{:type "chat-created" :clock-value 0 :name "blah"}]} - {:chat-id "chat-id" - :signature "a" - :from "id-1" - :events [{:type "members-added" :clock-value 10 :members [1 2]} - {:type "member-removed" :clock-value 11 :member 1}]}} - actual (->> (chats/normalize-chat {:chat-id "chat-id" - :membership-updates raw-events}) - :membership-updates - (into #{}))] - (is (= expected - actual))))) + (let [chat {:id "chat-id" + :color "color" + :name "name" + :chatType 3 + :members [{:id "a" + :admin true + :joined true} + {:id "b" + :admin true + :joined false} + {:id "c" + :admin false + :joined true} + {:id "d" + :admin false + :joined false}] + :lastClockValue 10 + :lastMessageContent "\"content\"" ;; goes through edn/read-string + :lastMessageContentType "type" + + :membershipUpdates [{:type "chat-created" + :name "test" + :clockValue 1 + :id "0xcdf4a63e0c98d0018cf532b3a48350bb80e292cc46249e3f876aaa65eb97a231" + :signature "b" + :from "a"} + {:type "members-added" + :clockValue 2 + :members ["a" "b"] + :id "0x1c34d6b4d022c432b7eb6b645e095791af0c6bdb626db7d705e6db0d7cd74b56" + :signature "b" + :from "a"}] + :unviewedMessagesCount 2 + :active true + :timestamp 2} + expected-chat {:public? false + :group-chat true + :color "color" + :last-message-content "content" + :last-message-content-type "type" + + :contacts #{"a" "b" "c" "d"} + :last-clock-value 10 + :admins #{"a" "b"} + :members-joined #{"a" "c"} + :name "name" + :membership-updates [{:chat-id "chat-id" + :from "a" + :signature "b" + :events [{:type "chat-created" + :name "test" + :clock-value 1} + {:type "members-added" + :clock-value 2 + :members ["a" "b"]}]}] + :unviewed-messages-count 2 + :is-active true + :group-chat-local-version 1 + :chat-id "chat-id" + :timestamp 2}] + (testing "from-rpc" + (is (= expected-chat (chats/<-rpc chat)))))) (deftest marshal-membership-updates-test (let [raw-updates [{:chat-id "chat-id" @@ -46,8 +148,8 @@ :from "id-2" :events [{:type "members-added" :clock-value 10 :members [1 2]} {:type "member-removed" :clock-value 11 :member 1}]}] - expected #{{:type "members-added" :clock-value 10 :from "id-2" :members [1 2] :signature "a" :id "0xb7690375de21da4890d2d5acca8b56e327d9eb75fd3b4bcceca4bf1679c2f830"} - {:type "member-removed" :clock-value 11 :from "id-2" :member 1 :signature "a" :id "0x2a66f195abf6e6903c4245e372e1e2e6aea2b2c0a74ad03080a313e94197a64f"} - {:type "chat-created" :clock-value 0 :from "id-1" :name "blah" :signature "b" :id "0x7fad22accf1dec64daedf83e7af19b0dcde8c5facfb479874a48da5fb6967e07"}} + expected #{{:type "members-added" :clockValue 10 :from "id-2" :members [1 2] :signature "a" :id "0xb7690375de21da4890d2d5acca8b56e327d9eb75fd3b4bcceca4bf1679c2f830"} + {:type "member-removed" :clockValue 11 :from "id-2" :member 1 :signature "a" :id "0x2a66f195abf6e6903c4245e372e1e2e6aea2b2c0a74ad03080a313e94197a64f"} + {:type "chat-created" :clockValue 0 :from "id-1" :name "blah" :signature "b" :id "0x7fad22accf1dec64daedf83e7af19b0dcde8c5facfb479874a48da5fb6967e07"}} actual (into #{} (chats/marshal-membership-updates raw-updates))] (is (= expected actual)))) diff --git a/test/cljs/status_im/test/group_chats/core.cljs b/test/cljs/status_im/test/group_chats/core.cljs index 44d304a731..944d6498b5 100644 --- a/test/cljs/status_im/test/group_chats/core.cljs +++ b/test/cljs/status_im/test/group_chats/core.cljs @@ -1,5 +1,6 @@ (ns status-im.test.group-chats.core (:require [cljs.test :refer-macros [deftest is testing]] + [status-im.ethereum.json-rpc :as json-rpc] [status-im.utils.clocks :as utils.clocks] [status-im.utils.config :as config] [status-im.group-chats.core :as group-chats])) @@ -492,7 +493,8 @@ :a "a-value"}])))) (deftest remove-group-chat-test - (with-redefs [utils.clocks/send inc] + (with-redefs [json-rpc/call (constantly nil) + utils.clocks/send inc] (let [cofx {:db {:chats {chat-id {:admins #{member-1 member-2} :name "chat-name" :chat-id chat-id diff --git a/test/cljs/status_im/test/pairing/core.cljs b/test/cljs/status_im/test/pairing/core.cljs index 77a9ade020..1dc79f34ad 100644 --- a/test/cljs/status_im/test/pairing/core.cljs +++ b/test/cljs/status_im/test/pairing/core.cljs @@ -2,6 +2,7 @@ (:require [cljs.test :refer-macros [deftest is testing]] [status-im.transport.message.pairing :as transport.pairing] [status-im.utils.identicon :as identicon] + [status-im.utils.pairing :as pairing.utils] [status-im.utils.config :as config] [status-im.pairing.core :as pairing])) @@ -308,11 +309,18 @@ (deftest has-paired-installations-test (testing "no paired devices" - (is (not (pairing/has-paired-installations? {:db {:pairing/installations {"1" {} - "2" {}}}})))) + (is (not (pairing.utils/has-paired-installations? {:db {:multiaccount {:installation-id "1"} + :pairing/installations {"1" {:installation-id "1" + :enabled? true} + "2" {:installation-id "2"} + "3" {:installation-id "3"}}}})))) (testing "has paired devices" - (is (pairing/has-paired-installations? {:db {:pairing/installations {"1" {} - "2" {:enabled? true}}}})))) + (is (pairing.utils/has-paired-installations? {:db {:pairing/installations {:multiaccount {:instllation-id "1"} + "1" {:installation-id "1" + :enabled? true} + "2" {:installation-id "2"} + "3" {:installation-id "3" + :enabled? true}}}})))) (deftest sort-installations (let [id "0" diff --git a/test/cljs/status_im/test/sign_in/flow.cljs b/test/cljs/status_im/test/sign_in/flow.cljs index 8a78c6616e..3e7ce26b3b 100644 --- a/test/cljs/status_im/test/sign_in/flow.cljs +++ b/test/cljs/status_im/test/sign_in/flow.cljs @@ -38,8 +38,7 @@ cofx {:db db :web3 :web3 :all-contacts data/all-contacts - :all-installations [] - :get-all-stored-chats data/get-chats} + :all-installations []} efx (events/multiaccount-change-success cofx [nil "address"]) new-db (:db efx)] (testing "Starting node." @@ -52,8 +51,6 @@ (is (= [:home nil] (efx :status-im.ui.screens.navigation/navigate-to)))) (testing "Multiaccount selected." (is (contains? new-db :multiaccount))) - (testing "Chats initialized." - (is (= 3 (count (:chats new-db))))) (testing "Contacts initialized." (is (= 2 (count (:contacts/contacts new-db)))))))) diff --git a/test/cljs/status_im/test/transport/core.cljs b/test/cljs/status_im/test/transport/core.cljs index 24a4ebbc83..65427c8310 100644 --- a/test/cljs/status_im/test/transport/core.cljs +++ b/test/cljs/status_im/test/transport/core.cljs @@ -14,8 +14,6 @@ :sym-key "sk3"} "4" {:topic "topic-4"}} :semaphores #{}}}] - (testing "it loads the filters" - (is (:filters/load-filters (transport/init-whisper cofx)))) (testing "custom mailservers" (let [ms-1 {:id "1" :fleet :eth.beta