Contact refactoring

This commit is contained in:
janherich 2018-04-09 09:59:45 +02:00
parent 067ea99db5
commit f406feacc7
No known key found for this signature in database
GPG Key ID: C23B473AFBE94D13
33 changed files with 667 additions and 1452 deletions

View File

@ -3,4 +3,4 @@
(def figwheel-urls { (def figwheel-urls {
:ios "ws://localhost:3449/figwheel-ws" :ios "ws://localhost:3449/figwheel-ws"
:android "ws://10.0.2.2:3449/figwheel-ws" :android "ws://10.0.2.2:3449/figwheel-ws"
}) })

1098
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -57,7 +57,7 @@
"react-native-testfairy": "2.8.0", "react-native-testfairy": "2.8.0",
"react-native-udp": "2.2.1", "react-native-udp": "2.2.1",
"react-native-webview-bridge": "github:status-im/react-native-webview-bridge#feature/camera-permissions", "react-native-webview-bridge": "github:status-im/react-native-webview-bridge#feature/camera-permissions",
"realm": "2.0.7", "realm": "2.3.3",
"rn-snoopy": "github:status-im/rn-snoopy", "rn-snoopy": "github:status-im/rn-snoopy",
"string_decoder": "0.10.31", "string_decoder": "0.10.31",
"url": "0.10.3", "url": "0.10.3",

View File

@ -13,7 +13,22 @@
"Dentacoin", "Dentacoin",
"Augur", "Augur",
"Ethlance", "Ethlance",
"Commiteth" "Commiteth",
"cryptokitties",
"cryptopunks",
"name-bazaar",
"cent",
"erc-dex",
"oasis-direct",
"etherbots",
"peepeth",
"hexel",
"kyber",
"bancor",
"opensea",
"decentraland",
"cryptocribs",
"cryptofighters"
] ]
}, },
"state-of-dapps": "state-of-dapps":
@ -26,9 +41,7 @@
[ [
"flight-delays-suck", "flight-delays-suck",
"FirstBlood", "FirstBlood",
"auction-house", "auction-house"
"gnosis",
"mkr-market"
] ]
} }
} }

View File

@ -26,7 +26,7 @@
"en": "Jarrad" "en": "Jarrad"
}, },
"photo-path": "contacts://jarrad", "photo-path": "contacts://jarrad",
"add-chat?": false, "public-key": "0x0428c9d6c1aaaa8369a7c63819684f30e34396dc0907d49afeac85a0a774ccb919b3482097d992e66bcc538e7a0c6acf874c77748f396f53c0a102e10d1a37765b",
"dapp?": false "dapp?": false
}, },
@ -42,7 +42,6 @@
{ {
"en": "http://auctionhouse.dappbench.com" "en": "http://auctionhouse.dappbench.com"
}, },
"groups": ["state-of-dapps"],
"description": "Decentralized auctions for on-chain assets." "description": "Decentralized auctions for on-chain assets."
}, },
@ -58,7 +57,6 @@
{ {
"en": "https://fdd.etherisc.com" "en": "https://fdd.etherisc.com"
}, },
"groups": ["state-of-dapps"],
"description": "Get instant payout in case your flight is late." "description": "Get instant payout in case your flight is late."
}, },
@ -74,7 +72,6 @@
{ {
"en": "https://app.firstblood.io" "en": "https://app.firstblood.io"
}, },
"groups": ["state-of-dapps"],
"description": "ESports for Everyone! A platform that lets players challenge the field and win rewards." "description": "ESports for Everyone! A platform that lets players challenge the field and win rewards."
}, },
@ -88,9 +85,8 @@
"dapp?": true, "dapp?": true,
"dapp-url": "dapp-url":
{ {
"en": "https://district0x.github.io/ethlance/resources/public/" "en": "https://district0x.github.io/ethlance/resources/public/"
}, },
"groups": ["dapps"],
"description": "The future of work is now. Hire people or work yourself in return for ETH." "description": "The future of work is now. Hire people or work yourself in return for ETH."
}, },
@ -106,121 +102,106 @@
{ {
"en": "https://www.cryptokitties.co" "en": "https://www.cryptokitties.co"
}, },
"groups": ["dapps"],
"description": "Collect and breed adorable digital cats." "description": "Collect and breed adorable digital cats."
}, },
"cryptopunks": { "cryptopunks": {
"name" : {"en" : "CryptoPunks"}, "name" : {"en" : "CryptoPunks"},
"description": "10,000 unique collectible punks", "description": "10,000 unique collectible punks",
"dapp-url": {"en" :"https://www.larvalabs.com/cryptopunks"}, "dapp-url": {"en" :"https://www.larvalabs.com/cryptopunks"},
"groups": ["dapps"], "dapp?": true,
"dapp?": true, "photo-path": "contacts://cryptopunks"
"photo-path": "contacts://cryptopunks" },
}, "name-bazaar": {
"name-bazaar": { "name" : {"en" : "Name Bazaar"},
"name" : {"en" : "Name Bazaar"}, "description": "ENS name marketplace",
"description": "ENS name marketplace", "dapp-url": {"en": "https://namebazaar.io"},
"dapp-url": {"en": "https://namebazaar.io"}, "dapp?": true,
"groups": ["dapps"], "photo-path": "contacts://name-bazaar"
"dapp?": true, },
"photo-path": "contacts://name-bazaar" "cent": {
}, "name" : {"en" : "Cent"},
"cent": { "description": "Get wisdom, get money",
"name" : {"en" : "Cent"}, "dapp-url": {"en" : "https://beta.cent.co"},
"description": "Get wisdom, get money", "dapp?": true,
"dapp-url": {"en" : "https://beta.cent.co"}, "photo-path": "contacts://cent"
"groups": ["dapps"], },
"dapp?": true, "erc-dex": {
"photo-path": "contacts://cent" "name" : {"en" : "ERC dEX"},
}, "description": "Trustless trading has arrived on Ethereum",
"erc-dex": { "dapp-url": {"en" : "https://app.ercdex.com/"},
"name" : {"en" : "ERC dEX"}, "dapp?": true,
"description": "Trustless trading has arrived on Ethereum", "photo-path": "contacts://erc-dex"
"dapp-url": {"en" : "https://app.ercdex.com/"}, },
"groups": ["dapps"], "oasis-direct": {
"dapp?": true, "name" : {"en" : "Oasis Direct"},
"photo-path": "contacts://erc-dex" "description": "The first decentralized instant exchange",
}, "dapp-url": {"en" : "https://oasis.direct/"},
"oasis-direct": { "dapp?": true,
"name" : {"en" : "Oasis Direct"}, "photo-path": "contacts://oasis-direct"
"description": "The first decentralized instant exchange", },
"dapp-url": {"en" : "https://oasis.direct/"}, "etherbots": {
"groups": ["dapps"], "name" : {"en" : "Etherbots"},
"dapp?": true, "description": "Robot wars on the Ethereum Platform",
"photo-path": "contacts://oasis-direct" "dapp-url": {"en" : "https://etherbots.io/"},
}, "dapp?": true,
"etherbots": { "photo-path": "contacts://etherbots"
"name" : {"en" : "Etherbots"}, },
"description": "Robot wars on the Ethereum Platform", "peepeth": {
"dapp-url": {"en" : "https://etherbots.io/"}, "name" : {"en" : "Peepeth"},
"groups": ["dapps"], "description": "Blockchain-powered microblogging",
"dapp?": true, "dapp-url": {"en" : "http://peepeth.com/"},
"photo-path": "contacts://etherbots" "dapp?": true,
}, "photo-path": "contacts://peepeth"
"peepeth": { },
"name" : {"en" : "Peepeth"}, "hexel": {
"description": "Blockchain-powered microblogging", "name" : {"en" : "Hexel"},
"dapp-url": {"en" : "http://peepeth.com/"}, "description": "Create your own cryptocurrency",
"groups": ["dapps"], "dapp-url": {"en" : "https://www.onhexel.com/"},
"dapp?": true, "dapp?": true,
"photo-path": "contacts://peepeth" "photo-path": "contacts://hexel"
}, },
"hexel": { "kyber": {
"name" : {"en" : "Hexel"}, "name" : {"en" : "Kyber"},
"description": "Create your own cryptocurrency", "description": "On-chain, instant and liquid platform for exchange and payment service",
"dapp-url": {"en" : "https://www.onhexel.com/"}, "dapp-url": {"en" : "https://web3.kyber.network"},
"groups": ["dapps"], "dapp?": true,
"dapp?": true, "photo-path": "contacts://kyber"
"photo-path": "contacts://hexel" },
}, "bancor": {
"kyber": { "name" : {"en" : "Bancor"},
"name" : {"en" : "Kyber"}, "description": "Bancor is a decentralized liquidity network",
"description": "On-chain, instant and liquid platform for exchange and payment service", "dapp-url": {"en" : "https://www.bancor.network/"},
"dapp-url": {"en" : "https://web3.kyber.network"}, "dapp?": true,
"groups": ["dapps"], "photo-path": "contacts://bancor"
"dapp?": true, },
"photo-path": "contacts://kyber" "opensea": {
}, "name" : {"en" : "OpenSea"},
"bancor": { "description": "The largest decentralized marketplace for cryptogoods",
"name" : {"en" : "Bancor"}, "dapp-url": {"en" : "https://opensea.io"},
"description": "Bancor is a decentralized liquidity network", "dapp?": true,
"dapp-url": {"en" : "https://www.bancor.network/"}, "photo-path": "contacts://opensea"
"groups": ["dapps"], },
"dapp?": true, "decentraland": {
"photo-path": "contacts://bancor" "name" : {"en" : "Decentraland"},
}, "description": "Decentraland is a virtual reality platform powered by the Ethereum blockchain.",
"opensea": { "dapp-url": {"en" : "https://market.decentraland.org/"},
"name" : {"en" : "OpenSea"}, "dapp?": true,
"description": "The largest decentralized marketplace for cryptogoods", "photo-path": "contacts://decentraland"
"dapp-url": {"en" : "https://opensea.io"}, },
"groups": ["dapps"], "cryptocribs": {
"dapp?": true, "name" : {"en" : "CryptoCribs"},
"photo-path": "contacts://opensea" "description": "Travel the globe. Pay in crypto.",
}, "dapp-url": {"en" : "https://cryptocribs.com"},
"decentraland": { "dapp?": true,
"name" : {"en" : "Decentraland"}, "photo-path": "contacts://cryptocribs"
"description": "Decentraland is a virtual reality platform powered by the Ethereum blockchain.", },
"dapp-url": {"en" : "https://market.decentraland.org/"}, "cryptofighters": {
"groups": ["dapps"], "name" : {"en" : "CryptoFighters"},
"dapp?": true, "description": "Collect train and fight digital fighters.",
"photo-path": "contacts://decentraland" "dapp-url": {"en" : "https://cryptofighters.io"},
}, "dapp?": true,
"cryptocribs": { "photo-path": "contacts://cryptofighters"
"name" : {"en" : "CryptoCribs"}, }
"description": "Travel the globe. Pay in crypto.",
"dapp-url": {"en" : "https://cryptocribs.com"},
"groups": ["dapps"],
"dapp?": true,
"photo-path": "contacts://cryptocribs"
},
"cryptofighters": {
"name" : {"en" : "CryptoFighters"},
"description": "Collect train and fight digital fighters.",
"dapp-url": {"en" : "https://cryptofighters.io"},
"groups": ["dapps"],
"dapp?": true,
"photo-path": "contacts://cryptofighters"
}
} }

View File

@ -18,18 +18,16 @@
:content-type content-type}) :content-type content-type})
(def chat (def chat
{:chat-id constants/console-chat-id {:chat-id constants/console-chat-id
:name (i18n/label :t/status-console) :name (i18n/label :t/status-console)
:color default-chat-color :color default-chat-color
:group-chat false :group-chat false
:is-active true :is-active true
:unremovable? true :unremovable? true
:timestamp (.getTime (js/Date.)) :timestamp (.getTime (js/Date.))
:photo-path (str "contacts://" constants/console-chat-id) :photo-path (str "contacts://" constants/console-chat-id)
:contacts [{:identity constants/console-chat-id :contacts [constants/console-chat-id]
:text-color "#FFFFFF" :last-clock-value 0})
:background-color "#AB7967"}]
:last-clock-value 0})
(def contact (def contact
{:whisper-identity constants/console-chat-id {:whisper-identity constants/console-chat-id

View File

@ -7,10 +7,14 @@
[status-im.chat.models :as models] [status-im.chat.models :as models]
[status-im.chat.console :as console] [status-im.chat.console :as console]
[status-im.chat.constants :as chat.constants] [status-im.chat.constants :as chat.constants]
[status-im.commands.events.loading :as events.loading]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.list-selection :as list-selection]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.group.events :as group.events]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.transport.message.core :as transport] [status-im.utils.contacts :as utils.contacts]
[status-im.transport.core :as transport]
[status-im.transport.message.core :as transport.message]
[status-im.transport.message.v1.protocol :as protocol] [status-im.transport.message.v1.protocol :as protocol]
[status-im.transport.message.v1.public-chat :as public-chat] [status-im.transport.message.v1.public-chat :as public-chat]
[status-im.transport.message.v1.group-chat :as group-chat] [status-im.transport.message.v1.group-chat :as group-chat]
@ -81,36 +85,57 @@
:data-store/update-message (-> (get-in new-db msg-path) (select-keys [:message-id :user-statuses]))}))) :data-store/update-message (-> (get-in new-db msg-path) (select-keys [:message-id :user-statuses]))})))
(defn init-console-chat (defn init-console-chat
[{:keys [chats] :as db}] [{:keys [db] :as cofx}]
(if (chats constants/console-chat-id) (when-not (get-in db [:chats constants/console-chat-id])
{:db db} {:db (-> db
{:db (-> db (assoc :current-chat-id constants/console-chat-id)
(assoc :current-chat-id constants/console-chat-id) (update :chats assoc constants/console-chat-id console/chat))
(update :chats assoc constants/console-chat-id console/chat)) :data-store/save-chat console/chat}))
:dispatch [:add-contacts [console/contact]]
:data-store/save-chat console/chat
:data-store/save-contact console/contact}))
(handlers/register-handler-fx (defn- add-default-contacts
:init-console-chat [{:keys [db default-contacts] :as cofx}]
(fn [{:keys [db]} _] (let [new-contacts (-> {}
(init-console-chat db))) (into (map (fn [[id props]]
(let [contact-id (name id)]
[contact-id {:whisper-identity contact-id
:address (utils.contacts/public-key->address contact-id)
:name (-> props :name :en)
:photo-path (:photo-path props)
:public-key (:public-key props)
:unremovable? (-> props :unremovable? boolean)
:hide-contact? (-> props :hide-contact? boolean)
:pending? (-> props :pending? boolean)
:dapp? (:dapp? props)
:dapp-url (-> props :dapp-url :en)
:bot-url (:bot-url props)
:description (:description props)}])))
default-contacts)
(assoc constants/console-chat-id console/contact))
existing-contacts (:contacts/contacts db)
contacts-to-add (select-keys new-contacts (set/difference (set (keys new-contacts))
(set (keys existing-contacts))))]
(handlers/merge-fx cofx
{:db (update db :contacts/contacts merge contacts-to-add)
:data-store/save-contacts (vals contacts-to-add)}
(events.loading/load-commands))))
(handlers/register-handler-fx (handlers/register-handler-fx
:initialize-chats :initialize-chats
[(re-frame/inject-cofx :data-store/all-chats) [(re-frame/inject-cofx :get-default-contacts-and-groups)
(re-frame/inject-cofx :data-store/all-chats)
(re-frame/inject-cofx :data-store/inactive-chat-ids) (re-frame/inject-cofx :data-store/inactive-chat-ids)
(re-frame/inject-cofx :data-store/get-messages) (re-frame/inject-cofx :data-store/get-messages)
(re-frame/inject-cofx :data-store/unviewed-messages) (re-frame/inject-cofx :data-store/unviewed-messages)
(re-frame/inject-cofx :data-store/message-ids) (re-frame/inject-cofx :data-store/message-ids)
(re-frame/inject-cofx :data-store/get-unanswered-requests)] (re-frame/inject-cofx :data-store/get-unanswered-requests)
(re-frame/inject-cofx :data-store/get-local-storage-data)]
(fn [{:keys [db (fn [{:keys [db
all-stored-chats all-stored-chats
inactive-chat-ids inactive-chat-ids
stored-unanswered-requests stored-unanswered-requests
get-stored-messages get-stored-messages
stored-unviewed-messages stored-unviewed-messages
stored-message-ids]} _] stored-message-ids] :as cofx} _]
(let [chat->message-id->request (reduce (fn [acc {:keys [chat-id message-id] :as request}] (let [chat->message-id->request (reduce (fn [acc {:keys [chat-id message-id] :as request}]
(assoc-in acc [chat-id message-id] request)) (assoc-in acc [chat-id message-id] request))
{} {}
@ -126,11 +151,13 @@
(-> chat-messages keys set)))))) (-> chat-messages keys set))))))
{} {}
all-stored-chats)] all-stored-chats)]
(-> db (handlers/merge-fx cofx
(assoc :chats chats {:db (assoc db
:deleted-chats inactive-chat-ids) :chats chats
init-console-chat :deleted-chats inactive-chat-ids)}
(update :dispatch-n conj [:load-default-contacts!]))))) (init-console-chat)
(group.events/add-default-groups)
(add-default-contacts)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:browse-link-from-message :browse-link-from-message
@ -147,7 +174,7 @@
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}] (defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}]
(when (and (seq message-ids) (when (and (seq message-ids)
(not (models/bot-only-chat? db chat-id))) (not (models/bot-only-chat? db chat-id)))
(transport/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx))) (transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
;;TODO (yenda) find a more elegant solution for system messages ;;TODO (yenda) find a more elegant solution for system messages
(defn- mark-messages-seen (defn- mark-messages-seen
@ -254,11 +281,20 @@
(fn [cofx [chat]] (fn [cofx [chat]]
(models/update-chat chat cofx))) (models/update-chat chat cofx)))
(defn- remove-transport [chat-id {:keys [db] :as cofx}]
(let [{:keys [group-chat public?]} (get-in db [:chats chat-id])]
;; if this is private group chat, we have to broadcast leave and unsubscribe after that
(if (and group-chat (not public?))
(handlers/merge-fx cofx (transport.message/send (group-chat/GroupLeave.) chat-id))
(handlers/merge-fx cofx (transport/unsubscribe-from-chat chat-id)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:remove-chat :remove-chat
[re-frame/trim-v] [re-frame/trim-v]
(fn [cofx [chat-id]] (fn [cofx [chat-id]]
(models/remove-chat chat-id cofx))) (handlers/merge-fx cofx
(models/remove-chat chat-id)
(remove-transport chat-id))))
(handlers/register-handler-fx (handlers/register-handler-fx
:remove-chat-and-navigate-home :remove-chat-and-navigate-home
@ -266,6 +302,7 @@
(fn [cofx [chat-id]] (fn [cofx [chat-id]]
(handlers/merge-fx cofx (handlers/merge-fx cofx
(models/remove-chat chat-id) (models/remove-chat chat-id)
(remove-transport chat-id)
(navigation/replace-view :home)))) (navigation/replace-view :home))))
(handlers/register-handler-fx (handlers/register-handler-fx
@ -312,28 +349,16 @@
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts) (models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
(navigation/navigate-to-clean :home) (navigation/navigate-to-clean :home)
(navigate-to-chat random-id {}) (navigate-to-chat random-id {})
(transport/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id))))) (transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
(defn- broadcast-leave [{:keys [public? chat-id]} cofx]
(when-not public?
(transport/send (group-chat/GroupLeave.) chat-id cofx)))
(handlers/register-handler-fx
:leave-group-chat
;; stop listening to group here
(fn [{{:keys [current-chat-id chats] :as db} :db :as cofx} _]
(handlers/merge-fx cofx
(models/remove-chat current-chat-id)
(navigation/replace-view :home)
(broadcast-leave (get chats current-chat-id)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:leave-group-chat? :leave-group-chat?
(fn [_ _] [re-frame/trim-v]
(fn [_ [chat-id]]
{:show-confirmation {:title (i18n/label :t/leave-confirmation) {:show-confirmation {:title (i18n/label :t/leave-confirmation)
:content (i18n/label :t/leave-group-chat-confirmation) :content (i18n/label :t/leave-group-chat-confirmation)
:confirm-button-text (i18n/label :t/leave) :confirm-button-text (i18n/label :t/leave)
:on-accept #(re-frame/dispatch [:leave-group-chat])}})) :on-accept #(re-frame/dispatch [:remove-chat-and-navigate-home chat-id])}}))
(handlers/register-handler-fx (handlers/register-handler-fx
:show-profile :show-profile

View File

@ -1,8 +1,7 @@
(ns status-im.chat.models (ns status-im.chat.models
(:require [status-im.ui.components.styles :as styles] (:require [status-im.ui.components.styles :as styles]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]))
[status-im.transport.core :as transport]))
(defn set-chat-ui-props (defn set-chat-ui-props
"Updates ui-props in active chat by merging provided kvs into them" "Updates ui-props in active chat by merging provided kvs into them"
@ -17,14 +16,14 @@
(defn- create-new-chat (defn- create-new-chat
[chat-id {:keys [db now]}] [chat-id {:keys [db now]}]
(let [name (get-in db [:contacts/contacts chat-id :name])] (let [name (get-in db [:contacts/contacts chat-id :name])]
{:chat-id chat-id {:chat-id chat-id
:name (or name (gfycat/generate-gfy chat-id)) :name (or name (gfycat/generate-gfy chat-id))
:color styles/default-chat-color :color styles/default-chat-color
:group-chat false :group-chat false
:is-active true :is-active true
:timestamp now :timestamp now
:contacts [{:identity chat-id}] :contacts [chat-id]
:last-clock-value 0})) :last-clock-value 0}))
(defn add-chat (defn add-chat
"Adds new chat to db & realm, if the chat with same id already exists, justs restores it" "Adds new chat to db & realm, if the chat with same id already exists, justs restores it"
@ -36,38 +35,38 @@
(assoc (get-stored-chat chat-id) :is-active true) (assoc (get-stored-chat chat-id) :is-active true)
(create-new-chat chat-id cofx)) (create-new-chat chat-id cofx))
chat-props)] chat-props)]
{:db (-> db {:db (-> db
(update :chats assoc chat-id new-chat) (update :chats assoc chat-id new-chat)
(update :deleted-chats (fnil disj #{}) chat-id)) (update :deleted-chats (fnil disj #{}) chat-id))
:data-store/save-chat new-chat}))) :data-store/save-chat new-chat})))
(defn add-public-chat (defn add-public-chat
"Adds new public group chat to db & realm" "Adds new public group chat to db & realm"
[topic {:keys [db now] :as cofx}] [topic {:keys [db now] :as cofx}]
(let [chat {:chat-id topic (let [chat {:chat-id topic
:name topic :name topic
:color styles/default-chat-color :color styles/default-chat-color
:group-chat true :group-chat true
:public? true :public? true
:is-active true :is-active true
:timestamp now :timestamp now
:last-clock-value 0}] :last-clock-value 0}]
{:db (assoc-in db [:chats topic] chat) {:db (assoc-in db [:chats topic] chat)
:data-store/save-chat chat})) :data-store/save-chat chat}))
(defn add-group-chat (defn add-group-chat
"Adds new private group chat to db & realm" "Adds new private group chat to db & realm"
[chat-id chat-name admin participants {:keys [db now] :as cofx}] [chat-id chat-name admin participants {:keys [db now] :as cofx}]
(let [chat {:chat-id chat-id (let [chat {:chat-id chat-id
:name chat-name :name chat-name
:color styles/default-chat-color :color styles/default-chat-color
:group-chat true :group-chat true
:group-admin admin :group-admin admin
:is-active true :is-active true
:timestamp now :timestamp now
:contacts (mapv (partial hash-map :identity) participants) :contacts participants
:last-clock-value 0}] :last-clock-value 0}]
{:db (assoc-in db [:chats chat-id] chat) {:db (assoc-in db [:chats chat-id] chat)
:data-store/save-chat chat})) :data-store/save-chat chat}))
;; TODO (yenda): there should be an option to update the timestamp ;; TODO (yenda): there should be an option to update the timestamp
@ -82,7 +81,7 @@
(let [chat (merge (or (get chats chat-id) (let [chat (merge (or (get chats chat-id)
(create-new-chat chat-id cofx)) (create-new-chat chat-id cofx))
chat-props)] chat-props)]
{:db (update-in db [:chats chat-id] merge chat) {:db (update-in db [:chats chat-id] merge chat)
:data-store/save-chat chat})))) :data-store/save-chat chat}))))
;; TODO (yenda): an upsert is suppose to add the entry if it doesn't ;; TODO (yenda): an upsert is suppose to add the entry if it doesn't
@ -98,17 +97,16 @@
(> timestamp removed-from-at))) (> timestamp removed-from-at)))
(defn remove-chat [chat-id {:keys [db] :as cofx}] (defn remove-chat [chat-id {:keys [db] :as cofx}]
(let [{:keys [chat-id group-chat debug?]} (get-in db [:chats chat-id]) (let [{:keys [chat-id group-chat debug?]} (get-in db [:chats chat-id])]
fx (cond-> {:db (-> db (cond-> {:db (-> db
(update :chats dissoc chat-id) (update :chats dissoc chat-id)
(update :deleted-chats (fnil conj #{}) chat-id))} (update :deleted-chats (fnil conj #{}) chat-id))}
(or group-chat debug?) (or group-chat debug?)
(assoc :data-store/delete-messages chat-id) (assoc :data-store/delete-messages chat-id)
debug? debug?
(assoc :data-store/delete-chat chat-id) (assoc :data-store/delete-chat chat-id)
(not debug?) (not debug?)
(assoc :data-store/deactivate-chat chat-id))] (assoc :data-store/deactivate-chat chat-id))))
(handlers/merge-fx cofx fx (transport/unsubscribe-from-chat chat-id))))
(defn bot-only-chat? [db chat-id] (defn bot-only-chat? [db chat-id]
(let [{:keys [group-chat contacts]} (get-in db [:chats chat-id])] (let [{:keys [group-chat contacts]} (get-in db [:chats chat-id])]

View File

@ -10,7 +10,7 @@
{} {}
name->ref)) name->ref))
(defn- is-dapp? [all-contacts {:keys [identity]}] (defn- is-dapp? [all-contacts identity]
(get-in all-contacts [identity :dapp?])) (get-in all-contacts [identity :dapp?]))
(defn command-name [{:keys [name]}] (defn command-name [{:keys [name]}]
@ -30,8 +30,7 @@
humans? (conj :humans) humans? (conj :humans)
public? (conj :public-chats)) public? (conj :public-chats))
global-access-scope (conj basic-access-scope :global) global-access-scope (conj basic-access-scope :global)
member-access-scopes (into #{} (map (comp (partial conj basic-access-scope) :identity)) member-access-scopes (into #{} (map (partial conj basic-access-scope)) contacts)]
contacts)]
(reduce (fn [acc access-scope] (reduce (fn [acc access-scope]
(merge acc (resolve-references all-contacts (merge acc (resolve-references all-contacts
(get-in access-scope->commands-responses [access-scope type])))) (get-in access-scope->commands-responses [access-scope type]))))

View File

@ -61,7 +61,7 @@
:icon-opts {:color :black :icon-opts {:color :black
:accessibility-label :chat-menu-button} :accessibility-label :chat-menu-button}
:handler #(on-options chat-id name group-chat public?)}]])] :handler #(on-options chat-id name group-chat public?)}]])]
(when-not (or public? group-chat) [add-contact-bar (-> contacts first :identity)])])) (when-not (or public? group-chat) [add-contact-bar (first contacts)])]))
(defmulti message-row (fn [{{:keys [type]} :row}] type)) (defmulti message-row (fn [{{:keys [type]} :row}] type))
@ -82,10 +82,10 @@
timeout (if platform/android? 50 0)] timeout (if platform/android? 50 0)]
{:component-did-mount (fn [_] {:component-did-mount (fn [_]
(animation/start (animation/start
(animation/anim-sequence (animation/anim-sequence
[(animation/anim-delay timeout) [(animation/anim-delay timeout)
(animation/spring opacity {:toValue 1 (animation/spring opacity {:toValue 1
:duration duration})])))} :duration duration})])))}
[react/with-activity-indicator [react/with-activity-indicator
{:style style/message-view-preview {:style style/message-view-preview
:preview [react/view style/message-view-preview]} :preview [react/view style/message-view-preview]}

View File

@ -46,23 +46,31 @@
{::evaluate-jail-n [{:jail-id whisper-identity {::evaluate-jail-n [{:jail-id whisper-identity
:jail-resource commands-snippet}]})) :jail-resource commands-snippet}]}))
(defn load-commands-for-bot
"This function takes coeffects, effects, bot contact and adds effects
for loading all commands/responses/subscriptions."
[cofx fx {:keys [whisper-identity bot-url]}]
(if-let [commands-resource (js-resources/get-resource bot-url)]
(merge-with into fx (evaluate-commands-in-jail cofx commands-resource whisper-identity))
(update fx :http-get-n conj {:url bot-url
:response-validator valid-network-resource?
:success-event-creator (fn [commands-resource]
[::evaluate-commands-in-jail commands-resource whisper-identity])
:failure-event-creator (fn [error-response]
[::proceed-loading whisper-identity {:error error-response}])})))
(defn load-commands (defn load-commands
"This function takes coeffects, effects and contact and adds effects "This function takes coeffects and produces effects
for loading all commands/responses/subscriptions. for loading all commands/responses/subscriptions for existing bot contacts.
It's currently working only for bots, eq we are not evaluating It's currently working only for bots, eq we are not evaluating
dapp resources in jail at all." dapp resources in jail at all."
[cofx fx {:keys [whisper-identity bot-url]}] [{:keys [db] :as cofx}]
(if bot-url (transduce (comp (map second)
(if-let [commands-resource (js-resources/get-resource bot-url)] (filter :bot-url))
(merge-with into fx (evaluate-commands-in-jail cofx commands-resource whisper-identity)) (completing (partial load-commands-for-bot cofx))
(update fx :http-get-n conj {:url bot-url {}
:response-validator valid-network-resource? (:contacts/contacts db)))
:success-event-creator (fn [commands-resource]
[::evaluate-commands-in-jail commands-resource whisper-identity])
:failure-event-creator (fn [error-response]
[::proceed-loading whisper-identity {:error error-response}])}))
fx))
(defn- add-exclusive-choices [initial-scope exclusive-choices] (defn- add-exclusive-choices [initial-scope exclusive-choices]
(reduce (fn [scopes-set exclusive-choices] (reduce (fn [scopes-set exclusive-choices]

View File

@ -179,4 +179,4 @@
::load-commands ::load-commands
[re-frame/trim-v (re-frame/inject-cofx :data-store/get-local-storage-data)] [re-frame/trim-v (re-frame/inject-cofx :data-store/get-local-storage-data)]
(fn [cofx [contact]] (fn [cofx [contact]]
(loading-events/load-commands cofx {} contact))) (loading-events/load-commands-for-bot cofx {} contact)))

View File

@ -72,43 +72,25 @@
(fn [] (fn []
(doto chat (doto chat
(aset "is-active" false) (aset "is-active" false)
(aset "removed-at" (datetime/timestamp))))))) (aset "removed-at" (datetime/timestamp)))))))
(defn get-contacts
[chat-id]
(-> @realm/account-realm
(realm/get-one-by-field :chat :chat-id chat-id)
(object/get "contacts")))
(defn- save-contacts
[identities contacts added-at]
(doseq [contact-identity identities]
(if-let [contact (.find contacts (fn [object _ _]
(= contact-identity (object/get object "identity"))))]
(doto contact
(aset "is-in-chat" true)
(aset "added-at" added-at))
(.push contacts (clj->js {:identity contact-identity
:added-at added-at})))))
(defn add-contacts (defn add-contacts
[chat-id identities] [chat-id identities]
(let [contacts (get-contacts chat-id) (let [chat (get-by-id-obj chat-id)
added-at (datetime/timestamp)] contacts (object/get chat "contacts")]
(realm/write @realm/account-realm (realm/write @realm/account-realm
#(save-contacts identities contacts added-at)))) #(aset chat "contacts"
(clj->js (into #{} (concat identities
(defn- delete-contacts (realm/js-object->clj contacts))))))))
[identities contacts]
(doseq [contact-identity identities]
(when-let [contact (.find contacts (fn [object _ _]
(= contact-identity (object/get object "identity"))))]
(realm/delete @realm/account-realm contact))))
(defn remove-contacts (defn remove-contacts
[chat-id identities] [chat-id identities]
(let [contacts (get-contacts chat-id)] (let [chat (get-by-id-obj chat-id)
(delete-contacts identities contacts))) contacts (object/get chat "contacts")]
(realm/write @realm/account-realm
#(aset chat "contacts"
(clj->js (remove (into #{} identities)
(realm/js-object->clj contacts)))))))
(defn save-property (defn save-property
[chat-id property-name value] [chat-id property-name value]

View File

@ -33,21 +33,15 @@
(when-let [group (realm/get-one-by-field @realm/account-realm :contact-group :group-id group-id)] (when-let [group (realm/get-one-by-field @realm/account-realm :contact-group :group-id group-id)]
(realm/delete @realm/account-realm group))) (realm/delete @realm/account-realm group)))
(defn get-contacts (defn- get-by-id-obj
[group-id] [group-id]
(-> @realm/account-realm (realm/get-one-by-field @realm/account-realm :contact-group :group-id group-id))
(realm/get-one-by-field :contact-group :group-id group-id)
(object/get "contacts")))
(defn- save-contacts
[identities contacts]
(doseq [contact-identity identities]
(when-not (.find contacts (fn [object _ _]
(= contact-identity (object/get object "identity"))))
(.push contacts (clj->js {:identity contact-identity})))))
(defn add-contacts (defn add-contacts
[group-id identities] [group-id identities]
(let [contacts (get-contacts group-id)] (let [group (get-by-id-obj group-id)
contacts (object/get group "contacts")]
(realm/write @realm/account-realm (realm/write @realm/account-realm
#(save-contacts identities contacts)))) #(aset group "contacts"
(clj->js (into #{} (concat identities
(realm/js-object->clj contacts))))))))

View File

@ -13,10 +13,7 @@
:optional true} :optional true}
:is-active :bool :is-active :bool
:timestamp :int :timestamp :int
:contacts {:type :list :contacts {:type "string[]"}
:objectType :chat-contact}
:unremovable? {:type :bool
:default false}
:removed-at {:type :int :removed-at {:type :int
:optional true} :optional true}
:removed-from-at {:type :int :removed-from-at {:type :int

View File

@ -6,7 +6,8 @@
:properties {:group-id :string :properties {:group-id :string
:name :string :name :string
:timestamp :int :timestamp :int
:order :int :order :int
:pending? {:type :bool :default false} :contacts {:type "string[]"}}})
:contacts {:type :list
:objectType :group-contact}}}) (defn migration [old-realm new-realm]
(log/debug "migrating group schema v1"))

View File

@ -1,13 +1,11 @@
(ns status-im.data-store.realm.schemas.account.v1.core (ns status-im.data-store.realm.schemas.account.v1.core
(:require [status-im.data-store.realm.schemas.account.v1.chat :as chat] (:require [status-im.data-store.realm.schemas.account.v1.chat :as chat]
[status-im.data-store.realm.schemas.account.v1.transport :as transport] [status-im.data-store.realm.schemas.account.v1.transport :as transport]
[status-im.data-store.realm.schemas.account.v1.chat-contact :as chat-contact]
[status-im.data-store.realm.schemas.account.v1.contact :as contact] [status-im.data-store.realm.schemas.account.v1.contact :as contact]
[status-im.data-store.realm.schemas.account.v1.message :as message] [status-im.data-store.realm.schemas.account.v1.message :as message]
[status-im.data-store.realm.schemas.account.v1.request :as request] [status-im.data-store.realm.schemas.account.v1.request :as request]
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status] [status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
[status-im.data-store.realm.schemas.account.v1.contact-group :as contact-group] [status-im.data-store.realm.schemas.account.v1.contact-group :as contact-group]
[status-im.data-store.realm.schemas.account.v1.group-contact :as group-contact]
[status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage] [status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage]
[status-im.data-store.realm.schemas.account.v1.browser :as browser] [status-im.data-store.realm.schemas.account.v1.browser :as browser]
[goog.object :as object] [goog.object :as object]
@ -16,14 +14,12 @@
[clojure.string :as string])) [clojure.string :as string]))
(def schema [chat/schema (def schema [chat/schema
chat-contact/schema
transport/schema transport/schema
contact/schema contact/schema
message/schema message/schema
request/schema request/schema
user-status/schema user-status/schema
contact-group/schema contact-group/schema
group-contact/schema
local-storage/schema local-storage/schema
browser/schema]) browser/schema])

View File

@ -15,7 +15,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:protocol/receive-whisper-message :protocol/receive-whisper-message
[re-frame/trim-v] [re-frame/trim-v (re-frame/inject-cofx :random-id)]
(fn [cofx [js-error js-message chat-id]] (fn [cofx [js-error js-message chat-id]]
(let [{:keys [payload sig]} (js->clj js-message :keywordize-keys true) (let [{:keys [payload sig]} (js->clj js-message :keywordize-keys true)
status-message (-> payload status-message (-> payload

View File

@ -21,7 +21,7 @@
(defrecord NewGroupKey [chat-id sym-key message] (defrecord NewGroupKey [chat-id sym-key message]
message/StatusMessage message/StatusMessage
(send [this _ cofx] (send [this _ cofx]
(let [public-keys (map :identity (get-in cofx [:db :chats chat-id :contacts]))] (let [public-keys (get-in cofx [:db :chats chat-id :contacts])]
(protocol/multi-send-with-pubkey {:public-keys public-keys (protocol/multi-send-with-pubkey {:public-keys public-keys
:chat-id chat-id :chat-id chat-id
:payload this} :payload this}
@ -32,6 +32,7 @@
:sym-key sym-key :sym-key sym-key
:on-success (fn [sym-key sym-key-id] :on-success (fn [sym-key sym-key-id]
(re-frame/dispatch [::add-new-sym-key {:chat-id chat-id (re-frame/dispatch [::add-new-sym-key {:chat-id chat-id
:signature signature
:sym-key sym-key :sym-key sym-key
:sym-key-id sym-key-id :sym-key-id sym-key-id
:message message}]))}} :message message}]))}}
@ -80,20 +81,20 @@
(handlers/merge-fx cofx (handlers/merge-fx cofx
(init-chat-if-new chat-id) (init-chat-if-new chat-id)
(send-new-group-key this chat-id))) (send-new-group-key this chat-id)))
(receive [this chat-id signature {:keys [now db] :as cofx}] (receive [this chat-id signature {:keys [now db random-id] :as cofx}]
(let [me (:current-public-key db)] (let [me (:current-public-key db)]
;; we have to check if we already have a chat, or it's a new one ;; we have to check if we already have a chat, or it's a new one
(if-let [{:keys [group-admin contacts] :as chat} (get-in db [:chats chat-id])] (if-let [{:keys [group-admin contacts] :as chat} (get-in db [:chats chat-id])]
;; update for existing group chat ;; update for existing group chat
(when (= signature group-admin) ;; make sure that admin is the one making changes (when (and (= signature group-admin) ;; make sure that admin is the one making changes
(not= (set contacts) (set participants))) ;; make sure it's actually changing something
(let [{:keys [removed added]} (participants-diff (set contacts) (set participants)) (let [{:keys [removed added]} (participants-diff (set contacts) (set participants))
admin-name (or (get-in cofx [db :contacts/contacts group-admin :name]) admin-name (or (get-in cofx [db :contacts/contacts group-admin :name])
group-admin) group-admin)]
message-id (transport.utils/message-id this)]
(if (removed me) ;; we were removed (if (removed me) ;; we were removed
(handlers/merge-fx cofx (handlers/merge-fx cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id message-id now (models.message/system-message chat-id random-id now
(str admin-name " " (i18n/label :t/removed-from-chat)))) (str admin-name " " (i18n/label :t/removed-from-chat))))
(models.chat/update-chat {:chat-id chat-id (models.chat/update-chat {:chat-id chat-id
:removed-from-at now :removed-from-at now
@ -101,7 +102,7 @@
(transport/unsubscribe-from-chat chat-id)) (transport/unsubscribe-from-chat chat-id))
(handlers/merge-fx cofx (handlers/merge-fx cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id message-id now (models.message/system-message chat-id random-id now
(prepare-system-message admin-name (prepare-system-message admin-name
added added
removed removed
@ -119,15 +120,14 @@
:payload this :payload this
:success-event [::unsubscribe-from-chat chat-id]} :success-event [::unsubscribe-from-chat chat-id]}
cofx)) cofx))
(receive [this chat-id signature {:keys [db now] :as cofx}] (receive [this chat-id signature {:keys [db now random-id] :as cofx}]
(let [message-id (transport.utils/message-id this) (let [me (:current-public-key db)
me (:current-public-key db)
participant-leaving-name (or (get-in db [:contacts/contacts signature :name]) participant-leaving-name (or (get-in db [:contacts/contacts signature :name])
signature)] signature)]
(when-not (= me signature) (when (get-in db [:chats chat-id]) ;; chat is present
(handlers/merge-fx cofx (handlers/merge-fx cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id message-id now (models.message/system-message chat-id random-id now
(str participant-leaving-name " " (i18n/label :t/left)))) (str participant-leaving-name " " (i18n/label :t/left))))
(group/participants-removed chat-id #{signature}) (group/participants-removed chat-id #{signature})
(send-new-group-key nil chat-id)))))) (send-new-group-key nil chat-id))))))
@ -160,8 +160,8 @@
(handlers/register-handler-fx (handlers/register-handler-fx
::add-new-sym-key ::add-new-sym-key
[re-frame/trim-v] [re-frame/trim-v (re-frame/inject-cofx :random-id)]
(fn [{:keys [db] :as cofx} [{:keys [sym-key-id sym-key chat-id message]}]] (fn [{:keys [db] :as cofx} [{:keys [sym-key-id sym-key chat-id signature message]}]]
(let [{:keys [web3 current-public-key]} db (let [{:keys [web3 current-public-key]} db
fx {:db (assoc-in db [:transport/chats chat-id :sym-key-id] sym-key-id) fx {:db (assoc-in db [:transport/chats chat-id :sym-key-id] sym-key-id)
:shh/add-filter {:web3 web3 :shh/add-filter {:web3 web3
@ -175,5 +175,5 @@
(assoc :sym-key sym-key))}}] (assoc :sym-key sym-key))}}]
;; if new sym-key is wrapping some message, call receive on it as well, if not just update the transport layer ;; if new sym-key is wrapping some message, call receive on it as well, if not just update the transport layer
(if message (if message
(handlers/merge-fx cofx fx (message/receive message chat-id chat-id)) (handlers/merge-fx cofx fx (message/receive message chat-id signature))
fx)))) fx))))

View File

@ -63,11 +63,17 @@
(defn- prepare-recipients [public-keys db] (defn- prepare-recipients [public-keys db]
(map (fn [public-key] (map (fn [public-key]
(select-keys (get-in db [:transport/chats public-key]) [:topic :sym-key-id])) (if-let [{:keys [topic sym-key-id]} (get-in db [:transport/chats public-key])]
{:topic topic
:sym-key-id sym-key-id}
{:topic (transport.utils/get-topic constants/contact-discovery)
:pub-key public-key}))
public-keys)) public-keys))
(defn multi-send-with-pubkey (defn multi-send-with-pubkey
"Sends payload to multiple participants selected by `:public-keys` key." "Sends payload to multiple participants selected by `:public-keys` key.
If there is already established symmetric key with the participant, uses that (for efficiency),
if not, uses asymetric encryption."
[{:keys [payload public-keys success-event]} {:keys [db] :as cofx}] [{:keys [payload public-keys success-event]} {:keys [db] :as cofx}]
(let [{:keys [current-public-key web3]} db (let [{:keys [current-public-key web3]} db
recipients (prepare-recipients public-keys db)] recipients (prepare-recipients public-keys db)]

View File

@ -82,11 +82,11 @@
:or {error-event :protocol/send-status-message-error}}] :or {error-event :protocol/send-status-message-error}}]
(let [whisper-message (update message :payload (comp transport.utils/from-utf8 (let [whisper-message (update message :payload (comp transport.utils/from-utf8
transit/serialize))] transit/serialize))]
(doseq [{:keys [sym-key-id topic]} recipients] (doseq [{:keys [sym-key-id pub-key topic]} recipients]
(post-message {:web3 web3 (post-message {:web3 web3
:whisper-message (assoc whisper-message :whisper-message (cond-> (assoc whisper-message :topic topic)
:symKeyID sym-key-id sym-key-id (assoc :symKeyID sym-key-id)
:topic topic) pub-key (assoc :pubKey pub-key))
:on-success (if success-event :on-success (if success-event
#(re-frame/dispatch success-event) #(re-frame/dispatch success-event)
#(log/debug :shh/post-success)) #(log/debug :shh/post-success))

View File

@ -22,12 +22,12 @@
:on-press #(re-frame/dispatch [:navigate-to :new-chat])}] :on-press #(re-frame/dispatch [:navigate-to :new-chat])}]
[action-button/action-separator] [action-button/action-separator]
;; TODO temporary removal before everything is fixed in group chats ;; TODO temporary removal before everything is fixed in group chats
#_[action-button/action-button [action-button/action-button
{:label (i18n/label :t/start-group-chat) {:label (i18n/label :t/start-group-chat)
:accessibility-label :start-group-chat-button :accessibility-label :start-group-chat-button
:icon :icons/contacts :icon :icons/contacts
:icon-opts {:color colors/blue} :icon-opts {:color colors/blue}
:on-press #(re-frame/dispatch [:open-contact-toggle-list :chat-group])}] :on-press #(re-frame/dispatch [:open-contact-toggle-list :chat-group])}]
[action-button/action-separator] [action-button/action-separator]
[action-button/action-button [action-button/action-button
{:label (i18n/label :t/new-public-group-chat) {:label (i18n/label :t/new-public-group-chat)

View File

@ -1,36 +1,22 @@
(ns status-im.ui.screens.contacts.events (ns status-im.ui.screens.contacts.events
(:require [cljs.reader :as reader] (:require [clojure.set :as set]
[cljs.reader :as reader]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.contacts :as utils.contacts] [status-im.utils.contacts :as utils.contacts]
[status-im.utils.random :as random] [status-im.constants :as constants]
[status-im.utils.js-resources :as js-res]
[status-im.i18n :refer [label]]
[taoensso.timbre :as log]
[status-im.utils.js-resources :as js-res]
[status-im.utils.datetime :as datetime]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.gfycat.core :as gfycat.core] [status-im.utils.gfycat.core :as gfycat.core]
[status-im.ui.screens.contacts.navigation] [status-im.ui.screens.contacts.navigation]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.group.events :as group.events]
[status-im.chat.console :as console-chat] [status-im.chat.console :as console-chat]
[status-im.chat.events :as chat.events] [status-im.chat.events :as chat.events]
[status-im.chat.models :as chat.models] [status-im.chat.models :as chat.models]
[status-im.commands.events.loading :as loading-events]
[status-im.js-dependencies :as js-dependencies]
[status-im.transport.message.core :as transport] [status-im.transport.message.core :as transport]
[status-im.transport.message.v1.contact :as message.v1.contact] [status-im.transport.message.v1.contact :as message.v1.contact]
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db])) [status-im.ui.screens.add-new.new-chat.db :as new-chat.db]))
;;;; COFX
(re-frame/reg-cofx
::get-default-contacts-and-groups
(fn [coeffects _]
(assoc coeffects
:default-contacts js-res/default-contacts
:default-groups js-res/default-contact-groups)))
;;;; Handlers ;;;; Handlers
(defn- update-contact [{:keys [whisper-identity] :as contact} {:keys [db]}] (defn- update-contact [{:keys [whisper-identity] :as contact} {:keys [db]}]
@ -38,84 +24,6 @@
{:db (update-in db [:contacts/contacts whisper-identity] merge contact) {:db (update-in db [:contacts/contacts whisper-identity] merge contact)
:data-store/save-contact contact})) :data-store/save-contact contact}))
(defn- update-pending-status [old-contacts {:keys [whisper-identity pending?] :as contact}]
(let [{old-pending :pending?
:as old-contact} (get old-contacts whisper-identity)
pending?' (if old-contact (and old-pending pending?) pending?)]
(assoc contact :pending? (boolean pending?'))))
(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- prepare-default-groups-events [groups default-groups]
[[:add-contact-groups
(for [[id {:keys [name contacts]}] default-groups
:let [id' (clojure.core/name id)]
:when (not (get groups id'))]
{:group-id id'
:name (:en name)
:order 0
:timestamp (datetime/timestamp)
:contacts (mapv #(hash-map :identity %) contacts)})]])
;; NOTE(oskarth): We now overwrite default contacts upon upgrade with default_contacts.json data.
(defn- prepare-default-contacts-events [contacts default-contacts]
(let [default-contacts
(for [[id {:keys [name photo-path public-key add-chat? pending? description
dapp? dapp-url dapp-hash bot-url unremovable? hide-contact?]}] default-contacts
:let [id' (clojure.core/name id)]]
{:whisper-identity id'
:address (public-key->address id')
:name (:en name)
:photo-path photo-path
:public-key public-key
:unremovable? (boolean unremovable?)
:hide-contact? (boolean hide-contact?)
:pending? pending?
:dapp? dapp?
:dapp-url (:en dapp-url)
:bot-url bot-url
:description description
:dapp-hash dapp-hash})
all-default-contacts (conj default-contacts console-chat/contact)]
[[:add-contacts all-default-contacts]]))
(defn- prepare-add-chat-events [contacts default-contacts]
(for [[id {:keys [name add-chat?]}] default-contacts
:let [id' (clojure.core/name id)]
:when (and (not (get contacts id')) add-chat?)]
[:add-chat id' {:name (:en name)}]))
(defn- prepare-add-contacts-to-groups-events [contacts default-contacts]
(let [groups (for [[id {:keys [groups]}] default-contacts
:let [id' (clojure.core/name id)]
:when (and (not (get contacts id')) groups)]
(for [group groups]
{:group-id group :whisper-identity id'}))
groups' (vals (group-by :group-id (flatten groups)))]
(for [contacts groups']
[:add-contacts-to-group
(:group-id (first contacts))
(mapv :whisper-identity contacts)])))
(handlers/register-handler-fx
:load-default-contacts!
[(re-frame/inject-cofx ::get-default-contacts-and-groups)]
(fn [{:keys [db default-contacts default-groups]} _]
(let [{:contacts/keys [contacts] :group/keys [contact-groups]} db]
{:dispatch-n (concat
(prepare-default-groups-events contact-groups default-groups)
(prepare-default-contacts-events contacts default-contacts)
(prepare-add-chat-events contacts default-contacts)
(prepare-add-contacts-to-groups-events contacts default-contacts))})))
(handlers/register-handler-fx (handlers/register-handler-fx
:load-contacts :load-contacts
[(re-frame/inject-cofx :data-store/get-all-contacts)] [(re-frame/inject-cofx :data-store/get-all-contacts)]
@ -124,24 +32,6 @@
contacts (into {} contacts-list)] contacts (into {} contacts-list)]
{:db (update db :contacts/contacts #(merge contacts %))}))) {:db (update db :contacts/contacts #(merge contacts %))})))
(handlers/register-handler-fx
:add-contacts
[(re-frame/inject-cofx :data-store/get-local-storage-data)]
(fn [{:keys [db] :as cofx} [_ new-contacts]]
(let [{:contacts/keys [contacts]} db
new-contacts' (->> new-contacts
(map #(update-pending-status contacts %))
;; NOTE(oskarth): Overwriting default contacts here
;;(remove #(identities (:whisper-identity %)))
(map #(vector (:whisper-identity %) %))
(into {}))
fx {:db (update db :contacts/contacts merge new-contacts')
:data-store/save-contacts (vals new-contacts')}]
(transduce (map second)
(completing (partial loading-events/load-commands (assoc cofx :db (:db fx))))
fx
new-contacts'))))
(defn- add-new-contact [{:keys [whisper-identity] :as contact} {:keys [db]}] (defn- add-new-contact [{:keys [whisper-identity] :as contact} {:keys [db]}]
(let [new-contact (assoc contact :pending? false)] (let [new-contact (assoc contact :pending? false)]
{:db (-> db {:db (-> db
@ -168,7 +58,7 @@
(reader/read-string contact-info) (reader/read-string contact-info)
(or (get contacts whisper-id) (or (get contacts whisper-id)
(utils.contacts/whisper-id->new-contact whisper-id))) (utils.contacts/whisper-id->new-contact whisper-id)))
(assoc :address (public-key->address whisper-id)))) (assoc :address (utils.contacts/public-key->address whisper-id))))
(defn add-contact [whisper-id {:keys [db] :as cofx}] (defn add-contact [whisper-id {:keys [db] :as cofx}]
(let [contact (build-contact whisper-id cofx)] (let [contact (build-contact whisper-id cofx)]

View File

@ -44,7 +44,7 @@
(remove #(true? (:dapp? %)) contacts))) (remove #(true? (:dapp? %)) contacts)))
(defn filter-group-contacts [group-contacts contacts] (defn filter-group-contacts [group-contacts contacts]
(let [group-contacts' (into #{} (map #(:identity %) group-contacts))] (let [group-contacts' (into #{} group-contacts)]
(filter #(group-contacts' (:whisper-identity %)) contacts))) (filter #(group-contacts' (:whisper-identity %)) contacts)))
(reg-sub :group-contacts (reg-sub :group-contacts
@ -59,7 +59,7 @@
(filter-group-contacts group-contacts contacts))) (filter-group-contacts group-contacts contacts)))
(defn filter-not-group-contacts [group-contacts contacts] (defn filter-not-group-contacts [group-contacts contacts]
(let [group-contacts' (into #{} (map #(:identity %) group-contacts))] (let [group-contacts' (into #{} group-contacts)]
(remove #(group-contacts' (:whisper-identity %)) contacts))) (remove #(group-contacts' (:whisper-identity %)) contacts)))
(reg-sub :all-not-added-group-contacts (reg-sub :all-not-added-group-contacts
@ -123,10 +123,7 @@
(defn chat-contacts [[chat contacts] [_ fn]] (defn chat-contacts [[chat contacts] [_ fn]]
(when chat (when chat
(let [current-participants (->> chat (let [current-participants (-> chat :contacts set)]
:contacts
(map :identity)
set)]
(fn #(current-participants (:whisper-identity %)) (fn #(current-participants (:whisper-identity %))
(vals contacts))))) (vals contacts)))))

View File

@ -275,10 +275,10 @@
{:dispatch-n (cond-> [[:initialize-account-db address] {:dispatch-n (cond-> [[:initialize-account-db address]
[:initialize-protocol address] [:initialize-protocol address]
[:initialize-sync-listener] [:initialize-sync-listener]
[:initialize-chats]
[:initialize-browsers]
[:load-contacts] [:load-contacts]
[:load-contact-groups] [:load-contact-groups]
[:initialize-chats]
[:initialize-browsers]
[:initialize-debugging {:address address}] [:initialize-debugging {:address address}]
[:send-account-update-if-needed] [:send-account-update-if-needed]
[:update-wallet] [:update-wallet]

View File

@ -20,9 +20,7 @@
:add-new-group-chat-participants :add-new-group-chat-participants
[(re-frame/inject-cofx :random-id)] [(re-frame/inject-cofx :random-id)]
(fn [{{:keys [current-chat-id selected-participants] :as db} :db now :now message-id :random-id :as cofx} _] (fn [{{:keys [current-chat-id selected-participants] :as db} :db now :now message-id :random-id :as cofx} _]
(let [new-identities (map #(hash-map :identity %) selected-participants) (let [participants (concat (get-in db [:chats current-chat-id :contacts]) selected-participants)
participants (concat (get-in db [:chats current-chat-id :contacts])
selected-participants)
contacts (:contacts/contacts db) contacts (:contacts/contacts db)
added-participants-names (map #(get-in contacts [% :name]) selected-participants)] added-participants-names (map #(get-in contacts [% :name]) selected-participants)]
(handlers/merge-fx cofx (handlers/merge-fx cofx
@ -39,8 +37,7 @@
:remove-group-chat-participants :remove-group-chat-participants
[re-frame/trim-v (re-frame/inject-cofx :random-id)] [re-frame/trim-v (re-frame/inject-cofx :random-id)]
(fn [{{:keys [current-chat-id] :as db} :db now :now message-id :random-id :as cofx} [removed-participants]] (fn [{{:keys [current-chat-id] :as db} :db now :now message-id :random-id :as cofx} [removed-participants]]
(let [participants (remove #(removed-participants (:identity %)) (let [participants (remove removed-participants (get-in db [:chats current-chat-id :contacts]))
(get-in db [:chats current-chat-id :contacts]))
contacts (:contacts/contacts db) contacts (:contacts/contacts db)
removed-participants-names (map #(get-in contacts [% :name]) removed-participants)] removed-participants-names (map #(get-in contacts [% :name]) removed-participants)]
(handlers/merge-fx cofx (handlers/merge-fx cofx

View File

@ -2,7 +2,7 @@
(defn participants-added [chat-id added-participants-set {:keys [db] :as cofx}] (defn participants-added [chat-id added-participants-set {:keys [db] :as cofx}]
(when (seq added-participants-set) (when (seq added-participants-set)
{:db (update-in db [:chats chat-id :contacts] concat (mapv #(hash-map :identity %) added-participants-set)) {:db (update-in db [:chats chat-id :contacts] concat added-participants-set)
:data-store/add-chat-contacts [chat-id added-participants-set]})) :data-store/add-chat-contacts [chat-id added-participants-set]}))
(defn participants-removed [chat-id removed-participants-set {:keys [now db] :as cofx}] (defn participants-removed [chat-id removed-participants-set {:keys [now db] :as cofx}]
@ -10,6 +10,5 @@
(let [{:keys [is-active timestamp]} (get-in db [:chats chat-id])] (let [{:keys [is-active timestamp]} (get-in db [:chats chat-id])]
;;TODO: not sure what this condition is for ;;TODO: not sure what this condition is for
(when (and is-active (>= now timestamp)) (when (and is-active (>= now timestamp))
{:db (update-in db [:chats chat-id :contacts] {:db (update-in db [:chats chat-id :contacts] (partial remove removed-participants-set))
(partial remove (comp removed-participants-set :identity)))
:data-store/remove-chat-contacts [chat-id removed-participants-set]})))) :data-store/remove-chat-contacts [chat-id removed-participants-set]}))))

View File

@ -13,11 +13,9 @@
(spec/def :group/name :global/not-empty-string) (spec/def :group/name :global/not-empty-string)
(spec/def :group/timestamp int?) (spec/def :group/timestamp int?)
(spec/def :group/pending? boolean?) (spec/def :group/pending? boolean?)
(spec/def :group/order int?) (spec/def :group/order int?)
(spec/def :group-contact/identity :global/not-empty-string) (spec/def :group/contact :global/not-empty-string)
(spec/def :group/contact (allowed-keys :req-un [:group-contact/identity]))
(spec/def :group/contacts (spec/nilable (spec/* :group/contact))) (spec/def :group/contacts (spec/nilable (spec/* :group/contact)))
@ -32,4 +30,4 @@
(spec/def :group/group-type (spec/nilable #{:chat-group :contact-group})) (spec/def :group/group-type (spec/nilable #{:chat-group :contact-group}))
(spec/def :group/selected-contacts (spec/nilable (spec/* string?))) (spec/def :group/selected-contacts (spec/nilable (spec/* string?)))
;;list of group ids ;;list of group ids
(spec/def :group/groups-order (spec/nilable (spec/* string?))) (spec/def :group/groups-order (spec/nilable (spec/* string?)))

View File

@ -1,109 +1,77 @@
(ns status-im.ui.screens.group.events (ns status-im.ui.screens.group.events
(:require [re-frame.core :refer [dispatch reg-fx reg-cofx inject-cofx]] (:require [clojure.set :as set]
[status-im.utils.handlers :refer [register-handler-db register-handler-fx]] [re-frame.core :as re-frame]
[status-im.ui.components.styles :refer [default-chat-color]] [status-im.utils.js-resources :as js-res]
[clojure.string :as string] [status-im.utils.handlers :as handlers]
[status-im.utils.random :as random] [status-im.ui.screens.group.navigation]))
[status-im.ui.screens.group.navigation]
[status-im.utils.datetime :as datetime] ;;;; COFX
[re-frame.core :as re-frame]))
(re-frame/reg-cofx
:get-default-contacts-and-groups
(fn [coeffects _]
(assoc coeffects
:default-contacts js-res/default-contacts
:default-groups js-res/default-contact-groups)))
;;;; Handlers ;;;; Handlers
(register-handler-db (handlers/register-handler-db
:deselect-contact :deselect-contact
(fn [db [_ id]] (fn [db [_ id]]
(update db :group/selected-contacts disj id))) (update db :group/selected-contacts disj id)))
(register-handler-db (handlers/register-handler-db
:select-contact :select-contact
(fn [db [_ id]] (fn [db [_ id]]
(update db :group/selected-contacts conj id))) (update db :group/selected-contacts conj id)))
(register-handler-db (handlers/register-handler-db
:deselect-participant :deselect-participant
(fn [db [_ id]] (fn [db [_ id]]
(update db :selected-participants disj id))) (update db :selected-participants disj id)))
(register-handler-db (handlers/register-handler-db
:select-participant :select-participant
(fn [db [_ id]] (fn [db [_ id]]
(update db :selected-participants conj id))) (update db :selected-participants conj id)))
(register-handler-fx (handlers/register-handler-fx
:create-new-contact-group :create-new-contact-group
[(re-frame/inject-cofx :now)] [re-frame/trim-v (re-frame/inject-cofx :now) (re-frame/inject-cofx :random-id)]
(fn [{{:group/keys [contact-groups selected-contacts] :as db} :db (fn [{{:group/keys [contact-groups selected-contacts] :as db} :db group-id :random-id now :now} [group-name]]
now :now} [_ group-name]] (let [new-group {:group-id group-id
(let [selected-contacts' (mapv #(hash-map :identity %) selected-contacts)
new-group {:group-id (random/id)
:name group-name :name group-name
:order (count contact-groups) :order (count contact-groups)
:timestamp now :timestamp now
:contacts selected-contacts'}] :contacts selected-contacts}]
{:db (update db :group/contact-groups merge {(:group-id new-group) new-group}) {:db (assoc-in db [:group/contact-groups group-id] new-group)
:data-store/save-contact-group new-group}))) :data-store/save-contact-group new-group})))
(register-handler-fx (defn add-default-groups
::update-contact-group [{:keys [db now default-groups]}]
(fn [{:keys [db]} [_ new-group]] (let [new-groups (into {}
{:db (update db :group/contact-groups merge {(:group-id new-group) new-group}) (map (fn [[id props]]
:data-store/save-contact-group new-group})) (let [group-id (name id)]
[group-id {:group-id group-id
:name (-> props :name :en)
:order 0
:timestamp now
:contacts (:contacts props)}])))
default-groups)
existing-groups (:group/contact-groups db)
groups-to-add (select-keys new-groups (set/difference (set (keys new-groups))
(set (keys existing-groups))))]
{:db (update db :group/contact-groups merge groups-to-add)
:data-store/save-contact-groups (vals groups-to-add)}))
(defn update-pending-status [old-groups {:keys [group-id pending?] :as group}] (handlers/register-handler-fx
(let [{old-pending :pending?
:as old-group} (get old-groups group-id)
pending?' (if old-pending (and old-pending pending?) pending?)]
(assoc group :pending? (boolean pending?'))))
(register-handler-fx
:add-contact-groups
(fn [{{:group/keys [contact-groups] :as db} :db} [_ new-groups]]
(let [identities (set (keys contact-groups))
old-groups-count (count identities)
new-groups' (->> new-groups
(map #(update-pending-status contact-groups %))
(remove #(identities (:group-id %)))
(map #(vector (:group-id %2) (assoc %2 :order %1)) (iterate inc old-groups-count))
(into {}))]
{:db (update db :group/contact-groups merge new-groups')
:data-store/save-contact-groups (into [] (vals new-groups'))})))
(register-handler-fx
:load-contact-groups :load-contact-groups
[(inject-cofx :data-store/get-all-contact-groups)] [(re-frame/inject-cofx :data-store/get-all-contact-groups)]
(fn [{:keys [db all-contact-groups]} _] (fn [{:keys [db all-contact-groups]} _]
{:db (assoc db :group/contact-groups all-contact-groups)})) {:db (assoc db :group/contact-groups all-contact-groups)}))
(defn move-item [v from to] (handlers/register-handler-fx
(if (< from to)
(concat (subvec v 0 from)
(subvec v (inc from) (inc to))
[(v from)]
(subvec v (inc to)))
(concat (subvec v 0 to)
[(v from)]
(subvec v to from)
(subvec v (inc from)))))
(register-handler-db
:change-contact-group-order
(fn [{:group/keys [groups-order] :as db} [_ from to]]
(if (>= to 0)
(assoc db :group/groups-order (move-item (vec groups-order) from to))
db)))
(register-handler-fx
:save-contact-group-order
(fn [{{:group/keys [contact-groups groups-order] :as db} :db} _]
(let [new-groups (mapv #(assoc (contact-groups (second %)) :order (first %))
(map-indexed vector (reverse groups-order)))]
{:db (update db
:group/contact-groups
merge (map #(vector (:group-id %) %) new-groups))
:data-store/save-contact-groups new-groups})))
(register-handler-fx
:set-contact-group-name :set-contact-group-name
(fn [{{:keys [new-chat-name] :group/keys [contact-group-id] :as db} :db} _] (fn [{{:keys [new-chat-name] :group/keys [contact-group-id] :as db} :db} _]
{:db (assoc-in db {:db (assoc-in db
@ -111,37 +79,20 @@
new-chat-name) new-chat-name)
:data-store/save-contact-group-property [contact-group-id :name new-chat-name]})) :data-store/save-contact-group-property [contact-group-id :name new-chat-name]}))
(register-handler-fx (handlers/register-handler-fx
:add-selected-contacts-to-group :add-selected-contacts-to-group
(fn [{{:group/keys [contact-groups contact-group-id selected-contacts] :as db} :db} _] (fn [{{:group/keys [contact-groups contact-group-id selected-contacts] :as db} :db} _]
(let [new-identities (mapv #(hash-map :identity %) selected-contacts)] {:db (update-in db
{:db (update-in db [:group/contact-groups contact-group-id :contacts]
[:group/contact-groups contact-group-id :contacts] #(into [] (set (concat % selected-contacts))))
#(into [] (set (concat % new-identities)))) :data-store/add-contacts-to-contact-group [contact-group-id selected-contacts]}))
:data-store/add-contacts-to-contact-group [contact-group-id selected-contacts]})))
(register-handler-fx (handlers/register-handler-fx
:add-contacts-to-group
(fn [{:keys [db]} [_ group-id contacts]]
(let [new-identities (mapv #(hash-map :identity %) contacts)]
(when (get-in db [:group/contact-groups group-id])
{:db (update-in db [:group/contact-groups group-id :contacts]
#(into [] (set (concat % new-identities))))
:data-store/add-contacts-to-contact-group [group-id contacts]}))))
(defn remove-contact-from-group [whisper-identity]
(fn [contacts]
(remove #(= whisper-identity (:identity %)) contacts)))
(register-handler-fx
:remove-contact-from-group :remove-contact-from-group
(fn [{:keys [db]} [_ whisper-identity group-id]] [re-frame/trim-v]
(let [{:group/keys [contact-groups]} db (fn [{:keys [db]} [whisper-identity group-id]]
group' (update (contact-groups group-id) :contacts (remove-contact-from-group whisper-identity))] (let [group (-> db
{:dispatch [::update-contact-group group']}))) (get-in [:group/contact-groups group-id])
(update :contacts (partial remove #(= whisper-identity %))))]
(register-handler-fx {:db (assoc-in db [:group/contact-groups group-id] group)
:delete-contact-group :data-store/save-contact-group group})))
(fn [{{:group/keys [contact-group-id] :as db} :db} _]
{:db (assoc-in db [:group/contact-groups contact-group-id :pending?] true)
:data-store/save-contact-group-property [contact-group-id :pending? true]}))

View File

@ -38,12 +38,10 @@
(defn actions [admin? chat-id] (defn actions [admin? chat-id]
(concat (concat
;; NOTE(goranjovic) - group chat participant removal has been temporarily disabled (when admin?
;; due to this bug - https://github.com/status-im/status-react/issues/3463 [{:label (i18n/label :add-members)
#_(when admin? :icon :icons/add
[{:label (i18n/label :add-members) :action #(re-frame/dispatch [:navigate-to :add-participants-toggle-list])}])
:icon :icons/add
:action #(re-frame/dispatch [:navigate-to :add-participants-toggle-list])}])
[{:label (i18n/label :t/clear-history) [{:label (i18n/label :t/clear-history)
:icon :icons/close :icon :icons/close
:action #(utils/show-confirmation (i18n/label :t/clear-history-title) :action #(utils/show-confirmation (i18n/label :t/clear-history-title)
@ -64,16 +62,14 @@
:action #(utils/show-confirmation (i18n/label :t/leave-group-title) :action #(utils/show-confirmation (i18n/label :t/leave-group-title)
(i18n/label :t/leave-group-confirmation) (i18n/label :t/leave-group-confirmation)
(i18n/label :t/leave-group-action) (i18n/label :t/leave-group-action)
(fn [] (re-frame/dispatch [:leave-group-chat]))) (fn [] (re-frame/dispatch [:remove-chat-and-navigate-home chat-id])))
:accessibility-label :leave-chat-button}])) :accessibility-label :leave-chat-button}]))
(defn contact-actions [contact] (defn contact-actions [contact]
[{:action #(re-frame/dispatch [:show-profile (:whisper-identity contact)]) [{:action #(re-frame/dispatch [:show-profile (:whisper-identity contact)])
:label (i18n/label :t/view-profile)} :label (i18n/label :t/view-profile)}
;; NOTE(goranjovic) - group chat participant removal has been temporarily disabled {:action #(re-frame/dispatch [:remove-group-chat-participants #{(:whisper-identity contact)}])
;; due to this bug - https://github.com/status-im/status-react/issues/3463 :label (i18n/label :t/remove-from-chat)}])
#_{:action #(re-frame/dispatch [:remove-group-chat-participants #{(:whisper-identity contact)}])
:label (i18n/label :t/remove-from-chat)}])
(defn render-contact [contact admin?] (defn render-contact [contact admin?]
[react/view [react/view

View File

@ -1,9 +1,19 @@
(ns status-im.utils.contacts (ns status-im.utils.contacts
(:require (:require [status-im.js-dependencies :as js-dependencies]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.gfycat.core :as gfycat])) [status-im.utils.gfycat.core :as gfycat]))
(defn whisper-id->new-contact [whisper-id] (defn whisper-id->new-contact [whisper-id]
{:name (gfycat/generate-gfy whisper-id) {:name (gfycat/generate-gfy whisper-id)
:photo-path (identicon/identicon whisper-id) :photo-path (identicon/identicon whisper-id)
:whisper-identity whisper-id}) :whisper-identity whisper-id})
(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))))

View File

@ -17,14 +17,13 @@
(deftest init-console-chat (deftest init-console-chat
(testing "initialising console if console is already added to chats, should not modify anything" (testing "initialising console if console is already added to chats, should not modify anything"
(let [db {:chats {const/console-chat-id console-chat/chat}} (let [db {:chats {const/console-chat-id console-chat/chat}}
fx (chat-events/init-console-chat db)] fx (chat-events/init-console-chat {:db db})]
(is (= db (:db fx))) (is (not fx))))
(is (= #{:db} (-> fx keys set)))))
(testing "initialising console without existing account and console chat not initialisated" (testing "initialising console without existing account and console chat not initialisated"
(let [fresh-db {:chats {} (let [fresh-db {:chats {}
:accounts/current-account-id nil} :accounts/current-account-id nil}
{:keys [db dispatch-n]} (chat-events/init-console-chat fresh-db)] {:keys [db dispatch-n]} (chat-events/init-console-chat {:db fresh-db})]
(is (= (:current-chat-id db) (is (= (:current-chat-id db)
(:chat-id console-chat/chat))) (:chat-id console-chat/chat)))
(is (= (:current-chat-id db) (is (= (:current-chat-id db)
@ -33,7 +32,7 @@
(testing "initialising console with existing account and console chat not initialisated" (testing "initialising console with existing account and console chat not initialisated"
(let [fresh-db {:chats {} (let [fresh-db {:chats {}
:accounts/current-account-id (:whisper-identity contact)} :accounts/current-account-id (:whisper-identity contact)}
{:keys [db dispatch-n]} (chat-events/init-console-chat fresh-db)] {:keys [db dispatch-n]} (chat-events/init-console-chat {:db fresh-db})]
(is (= (:current-chat-id db) (is (= (:current-chat-id db)
(:chat-id console-chat/chat))) (:chat-id console-chat/chat)))
(is (= (:current-chat-id db) (is (= (:current-chat-id db)

View File

@ -8,19 +8,17 @@
#{"0x1" :group-chats :anonymous :dapps} {:command {"command2" ["0x1" :command 4 "command2"]}} #{"0x1" :group-chats :anonymous :dapps} {:command {"command2" ["0x1" :command 4 "command2"]}}
#{"0x2" :personal-chats :anonymous :dapps} {:command {"command3" ["0x2" :command 2 "command3"]}} #{"0x2" :personal-chats :anonymous :dapps} {:command {"command3" ["0x2" :command 2 "command3"]}}
#{"0x2" :group-chats :anonymous :dapps} {:response {"response1" ["0x2" :response 4 "response1"]}}} #{"0x2" :group-chats :anonymous :dapps} {:response {"response1" ["0x2" :response 4 "response1"]}}}
:chats {"test1" {:contacts [{:identity "0x1"}] :chats {"test1" {:contacts ["0x1"]
:requests nil :requests nil
:seq-arguments ["arg1" "arg2"]} :seq-arguments ["arg1" "arg2"]}
"test2" {:contacts [{:identity "0x1"} "test2" {:contacts ["0x1" "0x2"]
{:identity "0x2"}]
:group-chat true :group-chat true
:requests {"id1" {:message-id "id1" :requests {"id1" {:message-id "id1"
:response "response1"}}} :response "response1"}}}
"test3" {:contacts [{:identity "0x1"}] "test3" {:contacts ["0x1"]
:requests {"id1" {:message-id "id1" :requests {"id1" {:message-id "id1"
:response "request1"}}} :response "request1"}}}
"test4" {:contacts [{:identity "0x1"} "test4" {:contacts ["0x1" "0x2"]
{:identity "0x2"}]
:group-chat true :group-chat true
:requests {"id2" {:message-id "id2" :requests {"id2" {:message-id "id2"
:response "response1"}} :response "response1"}}