diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 799de1049c..79200f7f13 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -7,7 +7,7 @@ [status-im.i18n :as i18n] [status-im.utils.core :as utils] [status-im.utils.config :as config] - [status-im.utils.contacts :as utils.contacts] + [status-im.contact.db :as contact.db] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.datetime :as time] [status-im.transport.message.group-chat :as message.group-chat] @@ -96,7 +96,7 @@ (let [chat-name' (chat.db/chat-name (get-in db [:chats chat-id]) from) contact-name' (if-let [contact-name (get-in db [:contacts/contacts from :name])] contact-name - (:name (utils.contacts/public-key->new-contact from))) + (:name (contact.db/public-key->new-contact from))) shown-chat-name (when-not (= chat-name' contact-name') chat-name') ; No point in repeating contact name if the chat name already contains the same name timestamp' (when-not (< (time/seconds-ago (time/to-date timestamp)) 15) (str " @ " (time/to-short-str timestamp))) diff --git a/src/status_im/contact/core.cljs b/src/status_im/contact/core.cljs index d6730dc5f3..2b5b0b267d 100644 --- a/src/status_im/contact/core.cljs +++ b/src/status_im/contact/core.cljs @@ -1,18 +1,16 @@ (ns status-im.contact.core - (:require [status-im.accounts.db :as accounts.db] - [status-im.data-store.contacts :as contacts-store] - [status-im.transport.message.protocol :as protocol] - [status-im.transport.message.contact :as message.contact] - [status-im.utils.contacts :as utils.contacts] - [status-im.utils.fx :as fx] - [re-frame.core :as re-frame] + (:require [re-frame.core :as re-frame] + [status-im.accounts.db :as accounts.db] [status-im.chat.models :as chat.models] + [status-im.contact.db :as contact.db] + [status-im.data-store.contacts :as contacts-store] [status-im.i18n :as i18n] + [status-im.transport.message.contact :as message.contact] + [status-im.transport.message.protocol :as protocol] [status-im.ui.screens.add-new.new-chat.db :as new-chat.db] [status-im.ui.screens.navigation :as navigation] - [status-im.utils.js-resources :as js-res] - [status-im.utils.utils :as utils] - [status-im.utils.fx :as fx])) + [status-im.utils.fx :as fx] + [status-im.utils.utils :as utils])) (fx/defn load-contacts [{:keys [db all-contacts]}] @@ -29,8 +27,8 @@ (defn build-contact [{{:keys [chats] :account/keys [account] :contacts/keys [contacts]} :db} public-key] (cond-> (assoc (or (get contacts public-key) - (utils.contacts/public-key->new-contact public-key)) - :address (utils.contacts/public-key->address public-key)) + (contact.db/public-key->new-contact public-key)) + :address (contact.db/public-key->address public-key)) (= public-key (:public-key account)) (assoc :name (:name account)))) @@ -110,7 +108,7 @@ :name name :address (or address (:address contact) - (utils.contacts/public-key->address public-key)) + (contact.db/public-key->address public-key)) :last-updated timestamp-ms ;;NOTE (yenda) in case of concurrent contact request :pending? (get contact :pending? true)} diff --git a/src/status_im/contact/db.cljs b/src/status_im/contact/db.cljs index 3696c0fee4..6d32fd97b0 100644 --- a/src/status_im/contact/db.cljs +++ b/src/status_im/contact/db.cljs @@ -1,5 +1,9 @@ (ns status-im.contact.db (:require [cljs.spec.alpha :as spec] + [status-im.js-dependencies :as js-dependencies] + [status-im.utils.identicon :as identicon] + [status-im.utils.gfycat.core :as gfycat] + [status-im.utils.ethereum.core :as ethereum] status-im.utils.db)) ;;;; DB @@ -77,3 +81,59 @@ (spec/def :contact/new-tag string?) (spec/def :ui/contact (spec/keys :opt [:contact/new-tag])) + +(defn public-key->new-contact [public-key] + {:name (gfycat/generate-gfy public-key) + :photo-path (identicon/identicon public-key) + :public-key public-key}) + +(defn public-key->address [public-key] + (let [length (count public-key) + normalized-key (case length + 132 (subs public-key 4) + 130 (subs public-key 2) + 128 public-key + nil)] + (when normalized-key + (subs (.sha3 js-dependencies/Web3.prototype normalized-key #js {:encoding "hex"}) 26)))) + +(defn- contact-by-address [[_ contact] address] + (when (ethereum/address= (:address contact) address) + contact)) + +(defn find-contact-by-address [contacts address] + (some #(contact-by-address % address) contacts)) + +(defn sort-contacts + [contacts] + (sort (fn [c1 c2] + (let [name1 (or (:name c1) (:address c1) (:public-key c1)) + name2 (or (:name c2) (:address c2) (:public-key c2))] + (compare (clojure.string/lower-case name1) + (clojure.string/lower-case name2)))) + (vals contacts))) + +(defn filter-dapps + [v dev-mode?] + (remove #(when-not dev-mode? (true? (:developer? %))) v)) + +(defn filter-group-contacts + [group-contacts contacts] + (let [group-contacts' (into #{} group-contacts)] + (filter #(group-contacts' (:public-key %)) contacts))) + +(defn query-chat-contacts + [{:keys [contacts]} all-contacts query-fn] + (let [participant-set (into #{} (filter identity) contacts)] + (query-fn (comp participant-set :public-key) (vals all-contacts)))) + +(defn get-all-contacts-in-group-chat + [members contacts current-account] + (let [current-account-contact (-> current-account + (select-keys [:name :photo-path :public-key])) + all-contacts (assoc contacts (:public-key current-account-contact) current-account-contact)] + (->> members + (map #(or (get all-contacts %) + (public-key->new-contact %))) + (remove :dapp?) + (sort-by (comp clojure.string/lower-case :name))))) diff --git a/src/status_im/contact/subs.cljs b/src/status_im/contact/subs.cljs index 7470003554..f0f353a972 100644 --- a/src/status_im/contact/subs.cljs +++ b/src/status_im/contact/subs.cljs @@ -1,164 +1,154 @@ (ns status-im.contact.subs - (:require [re-frame.core :refer [reg-sub subscribe]] - [status-im.utils.contacts :as utils.contacts] - [status-im.utils.identicon :as identicon])) + (:require [re-frame.core :as re-frame] + [status-im.utils.identicon :as identicon] + [status-im.contact.db :as contact.db])) -(reg-sub :get-current-contact-identity :contacts/identity) +(re-frame/reg-sub :get-current-contact-identity :contacts/identity) -(reg-sub :get-contacts :contacts/contacts) +(re-frame/reg-sub :get-contacts :contacts/contacts) -(reg-sub :get-dapps - (fn [db] - (:contacts/dapps db))) +(re-frame/reg-sub :get-dapps + (fn [db] + (:contacts/dapps db))) -(reg-sub :get-current-contact - :<- [:get-contacts] - :<- [:get-current-contact-identity] - (fn [[contacts identity]] - (contacts identity))) +(re-frame/reg-sub + :get-current-contact + :<- [:get-contacts] + :<- [:get-current-contact-identity] + (fn [[contacts identity]] + (contacts identity))) -(reg-sub :get-current-chat-contact - :<- [:get-contacts] - :<- [:get-current-chat-id] - (fn [[contacts chat-id]] - (get contacts chat-id))) +(re-frame/reg-sub + :get-current-chat-contact + :<- [:get-contacts] + :<- [:get-current-chat-id] + (fn [[contacts chat-id]] + (get contacts chat-id))) -(defn sort-contacts [contacts] - (sort (fn [c1 c2] - (let [name1 (or (:name c1) (:address c1) (:public-key c1)) - name2 (or (:name c2) (:address c2) (:public-key c2))] - (compare (clojure.string/lower-case name1) - (clojure.string/lower-case name2)))) - (vals contacts))) +(re-frame/reg-sub + :all-added-contacts + :<- [:get-contacts] + (fn [contacts] + (->> contacts + (remove (fn [[_ {:keys [pending? hide-contact?]}]] + (or pending? hide-contact?))) + (contact.db/sort-contacts)))) -(reg-sub :all-added-contacts - :<- [:get-contacts] - (fn [contacts] - (->> contacts - (remove (fn [[_ {:keys [pending? hide-contact?]}]] - (or pending? hide-contact?))) - (sort-contacts)))) +(re-frame/reg-sub + :all-added-people-contacts + :<- [:all-added-contacts] + (fn [contacts] + (remove :dapp? contacts))) -(reg-sub :all-added-people-contacts - :<- [:all-added-contacts] - (fn [contacts] - (remove :dapp? contacts))) +(re-frame/reg-sub + :all-dapps + :<- [:get-dapps] + :<- [:account/account] + (fn [[dapps {:keys [dev-mode?]}]] + (map (fn [m] (update m :data + #(contact.db/filter-dapps % dev-mode?))) + dapps))) -(defn- filter-dapps [v dev-mode?] - (remove #(when-not dev-mode? (true? (:developer? %))) v)) +(re-frame/reg-sub + :get-people-in-current-chat + :<- [:get-current-chat-contacts] + (fn [contacts] + (remove #(true? (:dapp? %)) contacts))) -(reg-sub :all-dapps - :<- [:get-dapps] - :<- [:account/account] - (fn [[dapps {:keys [dev-mode?]}]] - (map (fn [m] (update m :data #(filter-dapps % dev-mode?))) dapps))) +(re-frame/reg-sub + :get-contact-by-identity + :<- [:get-contacts] + :<- [:get-current-chat] + (fn [[all-contacts {:keys [contacts]}] [_ identity]] + (let [identity' (or identity (first contacts))] + (or + (get all-contacts identity') + (contact.db/public-key->new-contact identity'))))) -(reg-sub :get-people-in-current-chat - :<- [:get-current-chat-contacts] - (fn [contacts] - (remove #(true? (:dapp? %)) contacts))) +(re-frame/reg-sub + :contacts/dapps-by-name + :<- [:all-dapps] + (fn [dapps] + (reduce (fn [dapps-by-name category] + (merge dapps-by-name + (reduce (fn [acc {:keys [name] :as dapp}] + (assoc acc name dapp)) + {} + (:data category)))) + {} + dapps))) -(defn filter-group-contacts [group-contacts contacts] - (let [group-contacts' (into #{} group-contacts)] - (filter #(group-contacts' (:public-key %)) contacts))) +(re-frame/reg-sub + :get-contact-name-by-identity + :<- [:get-contacts] + :<- [:account/account] + (fn [[contacts current-account] [_ identity]] + (let [me? (= (:public-key current-account) identity)] + (if me? + (:name current-account) + (:name (contacts identity)))))) -(reg-sub :get-contact-by-identity - :<- [:get-contacts] - :<- [:get-current-chat] - (fn [[all-contacts {:keys [contacts]}] [_ identity]] - (let [identity' (or identity (first contacts))] - (or - (get all-contacts identity') - (utils.contacts/public-key->new-contact identity'))))) +(re-frame/reg-sub + :query-current-chat-contacts + :<- [:get-current-chat] + :<- [:get-contacts] + (fn [[chat contacts [_ query-fn]]] + (contact.db/query-chat-contacts chat contacts query-fn))) -(reg-sub :contacts/dapps-by-name - :<- [:all-dapps] - (fn [dapps] - (reduce (fn [dapps-by-name category] - (merge dapps-by-name - (reduce (fn [acc {:keys [name] :as dapp}] - (assoc acc name dapp)) - {} - (:data category)))) - {} - dapps))) +(re-frame/reg-sub + :get-all-contacts-not-in-current-chat + :<- [:query-current-chat-contacts remove] + (fn [contacts] + (->> contacts + (remove :dapp?) + (sort-by (comp clojure.string/lower-case :name))))) -(reg-sub :get-contact-name-by-identity - :<- [:get-contacts] - :<- [:account/account] - (fn [[contacts current-account] [_ identity]] - (let [me? (= (:public-key current-account) identity)] - (if me? - (:name current-account) - (:name (contacts identity)))))) +(re-frame/reg-sub + :get-current-chat-contacts + :<- [:get-current-chat] + :<- [:get-contacts] + :<- [:account/account] + (fn [[{:keys [contacts]} all-contacts current-account]] + (contact.db/get-all-contacts-in-group-chat contacts all-contacts current-account))) -(defn query-chat-contacts [[{:keys [contacts]} all-contacts] [_ query-fn]] - (let [participant-set (into #{} (filter identity) contacts)] - (query-fn (comp participant-set :public-key) (vals all-contacts)))) +(re-frame/reg-sub + :get-contacts-by-chat + (fn [[_ _ chat-id] _] + [(re-frame/subscribe [:get-chat chat-id]) + (re-frame/subscribe [:get-contacts])]) + (fn [[chat all-contacts [_ query-fn]]] + (contact.db/query-chat-contacts chat all-contacts query-fn))) -(reg-sub :query-current-chat-contacts - :<- [:get-current-chat] - :<- [:get-contacts] - query-chat-contacts) +(re-frame/reg-sub + :get-chat-photo + (fn [[_ chat-id] _] + [(re-frame/subscribe [:get-chat chat-id]) + (re-frame/subscribe [:get-contacts-by-chat filter chat-id])]) + (fn [[chat contacts] [_ chat-id]] + (when (and chat (not (:group-chat chat))) + (cond + (:photo-path chat) + (:photo-path chat) -(reg-sub :get-all-contacts-not-in-current-chat - :<- [:query-current-chat-contacts remove] - (fn [contacts] - (->> contacts - (remove :dapp?) - (sort-by (comp clojure.string/lower-case :name))))) + (pos? (count contacts)) + (:photo-path (first contacts)) -(defn get-all-contacts-in-group-chat - [members contacts current-account] - (let [current-account-contact (-> current-account - (select-keys [:name :photo-path :public-key])) - all-contacts (assoc contacts (:public-key current-account-contact) current-account-contact)] - (->> members - (map #(or (get all-contacts %) - (utils.contacts/public-key->new-contact %))) - (remove :dapp?) - (sort-by (comp clojure.string/lower-case :name))))) + :else + (identicon/identicon chat-id))))) -(reg-sub :get-current-chat-contacts - :<- [:get-current-chat] - :<- [:get-contacts] - :<- [:account/account] - (fn [[{:keys [contacts]} all-contacts current-account]] - (get-all-contacts-in-group-chat contacts all-contacts current-account))) +(re-frame/reg-sub + :get-contact-by-address + :<- [:get-contacts] + (fn [contacts [_ address]] + (contact.db/find-contact-by-address contacts address))) -(reg-sub :get-contacts-by-chat - (fn [[_ _ chat-id] _] - [(subscribe [:get-chat chat-id]) - (subscribe [:get-contacts])]) - query-chat-contacts) - -(reg-sub :get-chat-photo - (fn [[_ chat-id] _] - [(subscribe [:get-chat chat-id]) - (subscribe [:get-contacts-by-chat filter chat-id])]) - (fn [[chat contacts] [_ chat-id]] - (when (and chat (not (:group-chat chat))) - (cond - (:photo-path chat) - (:photo-path chat) - - (pos? (count contacts)) - (:photo-path (first contacts)) - - :else - (identicon/identicon chat-id))))) - -(reg-sub :get-contact-by-address - :<- [:get-contacts] - (fn [contacts [_ address]] - (utils.contacts/find-contact-by-address contacts address))) - -(reg-sub :get-contacts-by-address - :<- [:get-contacts] - (fn [contacts] - (reduce (fn [acc [_ {:keys [address] :as contact}]] - (if address - (assoc acc address contact) - acc)) - {} - contacts))) +(re-frame/reg-sub + :get-contacts-by-address + :<- [:get-contacts] + (fn [contacts] + (reduce (fn [acc [_ {:keys [address] :as contact}]] + (if address + (assoc acc address contact) + acc)) + {} + contacts))) diff --git a/src/status_im/ui/screens/desktop/main/chat/views.cljs b/src/status_im/ui/screens/desktop/main/chat/views.cljs index e3c46350a7..91929ef126 100644 --- a/src/status_im/ui/screens/desktop/main/chat/views.cljs +++ b/src/status_im/ui/screens/desktop/main/chat/views.cljs @@ -20,7 +20,7 @@ [status-im.ui.screens.desktop.main.tabs.profile.views :as profile.views] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.screens.desktop.main.chat.styles :as styles] - [status-im.utils.contacts :as utils.contacts] + [status-im.contact.db :as contact.db] [status-im.i18n :as i18n] [status-im.ui.screens.desktop.main.chat.events :as chat.events] [status-im.ui.screens.chat.message.message :as chat.message])) @@ -332,7 +332,7 @@ (views/defview chat-profile [] (views/letsubs [identity [:get-current-contact-identity] maybe-contact [:get-current-contact]] - (let [contact (or maybe-contact (utils.contacts/public-key->new-contact identity)) + (let [contact (or maybe-contact (contact.db/public-key->new-contact identity)) {:keys [pending? public-key]} contact] [react/view {:style styles/chat-profile-body} [profile.views/profile-badge contact] diff --git a/src/status_im/ui/screens/profile/contact/views.cljs b/src/status_im/ui/screens/profile/contact/views.cljs index ea1a089419..4600749cc0 100644 --- a/src/status_im/ui/screens/profile/contact/views.cljs +++ b/src/status_im/ui/screens/profile/contact/views.cljs @@ -1,15 +1,15 @@ (ns status-im.ui.screens.profile.contact.views - (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [re-frame.core :as re-frame] + [status-im.contact.db :as contact.db] [status-im.i18n :as i18n] - [status-im.utils.contacts :as utils.contacts] - [status-im.ui.components.react :as react] [status-im.ui.components.list.views :as list] - [status-im.ui.components.toolbar.view :as toolbar] + [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :as status-bar] - [status-im.ui.screens.profile.contact.styles :as styles] + [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.screens.profile.components.styles :as profile.components.styles] - [status-im.ui.screens.profile.components.views :as profile.components])) + [status-im.ui.screens.profile.components.views :as profile.components] + [status-im.ui.screens.profile.contact.styles :as styles]) + (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defn profile-contact-toolbar [] [toolbar/toolbar {} @@ -64,7 +64,7 @@ (defview profile [] (letsubs [identity [:get-current-contact-identity] maybe-contact [:get-current-contact]] - (let [contact (or maybe-contact (utils.contacts/public-key->new-contact identity))] + (let [contact (or maybe-contact (contact.db/public-key->new-contact identity))] [react/view profile.components.styles/profile [status-bar/status-bar] [profile-contact-toolbar] diff --git a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs index 01f1d23831..70b5275897 100644 --- a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs +++ b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs @@ -1,13 +1,13 @@ (ns status-im.ui.screens.wallet.choose-recipient.events - (:require [status-im.constants :as constants] + (:require [re-frame.core :as re-frame] + [status-im.constants :as constants] + [status-im.contact.db :as contact.db] [status-im.i18n :as i18n] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.eip681 :as eip681] - [status-im.utils.handlers :as handlers] - [status-im.utils.money :as money] [status-im.utils.ethereum.ens :as ens] - [re-frame.core :as re-frame] - [status-im.utils.contacts :as utils.contacts])) + [status-im.utils.handlers :as handlers] + [status-im.utils.money :as money])) (handlers/register-handler-fx :wallet/toggle-flashlight @@ -17,7 +17,7 @@ {:db (assoc-in db [:wallet :send-transaction :camera-flashlight] toggled-state)}))) (defn- find-address-name [db address] - (:name (utils.contacts/find-contact-by-address (:contacts/contacts db) address))) + (:name (contact.db/find-contact-by-address (:contacts/contacts db) address))) (defn- fill-request-details [db {:keys [address name value symbol gas gasPrice public-key from-chat?]}] {:pre [(not (nil? address))]} diff --git a/src/status_im/utils/contacts.cljs b/src/status_im/utils/contacts.cljs deleted file mode 100644 index e69e3f8f17..0000000000 --- a/src/status_im/utils/contacts.cljs +++ /dev/null @@ -1,27 +0,0 @@ -(ns status-im.utils.contacts - (:require [status-im.js-dependencies :as js-dependencies] - [status-im.utils.identicon :as identicon] - [status-im.utils.gfycat.core :as gfycat] - [status-im.utils.ethereum.core :as ethereum])) - -(defn public-key->new-contact [public-key] - {:name (gfycat/generate-gfy public-key) - :photo-path (identicon/identicon public-key) - :public-key public-key}) - -(defn public-key->address [public-key] - (let [length (count public-key) - normalized-key (case length - 132 (subs public-key 4) - 130 (subs public-key 2) - 128 public-key - nil)] - (when normalized-key - (subs (.sha3 js-dependencies/Web3.prototype normalized-key #js {:encoding "hex"}) 26)))) - -(defn- contact-by-address [[_ contact] address] - (when (ethereum/address= (:address contact) address) - contact)) - -(defn find-contact-by-address [contacts address] - (some #(contact-by-address % address) contacts)) diff --git a/test/cljs/status_im/test/contacts/subs.cljs b/test/cljs/status_im/test/contacts/db.cljs similarity index 92% rename from test/cljs/status_im/test/contacts/subs.cljs rename to test/cljs/status_im/test/contacts/db.cljs index 3b111ee300..facc57ea50 100644 --- a/test/cljs/status_im/test/contacts/subs.cljs +++ b/test/cljs/status_im/test/contacts/db.cljs @@ -1,7 +1,7 @@ -(ns status-im.test.contacts.subs +(ns status-im.test.contacts.db (:require [cljs.test :refer-macros [deftest is testing]] [status-im.utils.identicon :as identicon] - [status-im.contact.subs :as contacts-subs])) + [status-im.contact.db :as contact.db])) (deftest contacts-subs (testing "get-all-contacts-in-group-chat" @@ -35,9 +35,9 @@ :photo-path "photo2", :public-key "0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}] - (is (= (contacts-subs/get-all-contacts-in-group-chat chat-contact-ids - contacts - current-account) + (is (= (contact.db/get-all-contacts-in-group-chat chat-contact-ids + contacts + current-account) [{:name "Snappy Impressive Leonberger" :photo-path "generated" :public-key "0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"} diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index e1a56b04bc..cc72e68c37 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -1,6 +1,6 @@ (ns status-im.test.runner (:require [doo.runner :refer-macros [doo-tests]] - [status-im.test.contacts.subs] + [status-im.test.contacts.db] [status-im.test.data-store.chats] [status-im.test.data-store.realm.core] [status-im.test.extensions.core] @@ -69,8 +69,8 @@ (doo-tests 'status-im.test.utils.async 'status-im.test.chat.db + 'status-im.test.contacts.db 'status-im.test.chat.models - 'status-im.test.contacts.subs 'status-im.test.init.core 'status-im.test.data-store.chats 'status-im.test.data-store.realm.core