Contact refactoring
This commit is contained in:
parent
067ea99db5
commit
f406feacc7
File diff suppressed because it is too large
Load Diff
|
@ -57,7 +57,7 @@
|
|||
"react-native-testfairy": "2.8.0",
|
||||
"react-native-udp": "2.2.1",
|
||||
"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",
|
||||
"string_decoder": "0.10.31",
|
||||
"url": "0.10.3",
|
||||
|
|
|
@ -13,7 +13,22 @@
|
|||
"Dentacoin",
|
||||
"Augur",
|
||||
"Ethlance",
|
||||
"Commiteth"
|
||||
"Commiteth",
|
||||
"cryptokitties",
|
||||
"cryptopunks",
|
||||
"name-bazaar",
|
||||
"cent",
|
||||
"erc-dex",
|
||||
"oasis-direct",
|
||||
"etherbots",
|
||||
"peepeth",
|
||||
"hexel",
|
||||
"kyber",
|
||||
"bancor",
|
||||
"opensea",
|
||||
"decentraland",
|
||||
"cryptocribs",
|
||||
"cryptofighters"
|
||||
]
|
||||
},
|
||||
"state-of-dapps":
|
||||
|
@ -26,9 +41,7 @@
|
|||
[
|
||||
"flight-delays-suck",
|
||||
"FirstBlood",
|
||||
"auction-house",
|
||||
"gnosis",
|
||||
"mkr-market"
|
||||
"auction-house"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"en": "Jarrad"
|
||||
},
|
||||
"photo-path": "contacts://jarrad",
|
||||
"add-chat?": false,
|
||||
"public-key": "0x0428c9d6c1aaaa8369a7c63819684f30e34396dc0907d49afeac85a0a774ccb919b3482097d992e66bcc538e7a0c6acf874c77748f396f53c0a102e10d1a37765b",
|
||||
"dapp?": false
|
||||
},
|
||||
|
||||
|
@ -42,7 +42,6 @@
|
|||
{
|
||||
"en": "http://auctionhouse.dappbench.com"
|
||||
},
|
||||
"groups": ["state-of-dapps"],
|
||||
"description": "Decentralized auctions for on-chain assets."
|
||||
},
|
||||
|
||||
|
@ -58,7 +57,6 @@
|
|||
{
|
||||
"en": "https://fdd.etherisc.com"
|
||||
},
|
||||
"groups": ["state-of-dapps"],
|
||||
"description": "Get instant payout in case your flight is late."
|
||||
},
|
||||
|
||||
|
@ -74,7 +72,6 @@
|
|||
{
|
||||
"en": "https://app.firstblood.io"
|
||||
},
|
||||
"groups": ["state-of-dapps"],
|
||||
"description": "ESports for Everyone! A platform that lets players challenge the field and win rewards."
|
||||
},
|
||||
|
||||
|
@ -90,7 +87,6 @@
|
|||
{
|
||||
"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."
|
||||
},
|
||||
|
||||
|
@ -106,7 +102,6 @@
|
|||
{
|
||||
"en": "https://www.cryptokitties.co"
|
||||
},
|
||||
"groups": ["dapps"],
|
||||
"description": "Collect and breed adorable digital cats."
|
||||
},
|
||||
|
||||
|
@ -114,7 +109,6 @@
|
|||
"name" : {"en" : "CryptoPunks"},
|
||||
"description": "10,000 unique collectible punks",
|
||||
"dapp-url": {"en" :"https://www.larvalabs.com/cryptopunks"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://cryptopunks"
|
||||
},
|
||||
|
@ -122,7 +116,6 @@
|
|||
"name" : {"en" : "Name Bazaar"},
|
||||
"description": "ENS name marketplace",
|
||||
"dapp-url": {"en": "https://namebazaar.io"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://name-bazaar"
|
||||
},
|
||||
|
@ -130,7 +123,6 @@
|
|||
"name" : {"en" : "Cent"},
|
||||
"description": "Get wisdom, get money",
|
||||
"dapp-url": {"en" : "https://beta.cent.co"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://cent"
|
||||
},
|
||||
|
@ -138,7 +130,6 @@
|
|||
"name" : {"en" : "ERC dEX"},
|
||||
"description": "Trustless trading has arrived on Ethereum",
|
||||
"dapp-url": {"en" : "https://app.ercdex.com/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://erc-dex"
|
||||
},
|
||||
|
@ -146,7 +137,6 @@
|
|||
"name" : {"en" : "Oasis Direct"},
|
||||
"description": "The first decentralized instant exchange",
|
||||
"dapp-url": {"en" : "https://oasis.direct/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://oasis-direct"
|
||||
},
|
||||
|
@ -154,7 +144,6 @@
|
|||
"name" : {"en" : "Etherbots"},
|
||||
"description": "Robot wars on the Ethereum Platform",
|
||||
"dapp-url": {"en" : "https://etherbots.io/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://etherbots"
|
||||
},
|
||||
|
@ -162,7 +151,6 @@
|
|||
"name" : {"en" : "Peepeth"},
|
||||
"description": "Blockchain-powered microblogging",
|
||||
"dapp-url": {"en" : "http://peepeth.com/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://peepeth"
|
||||
},
|
||||
|
@ -170,7 +158,6 @@
|
|||
"name" : {"en" : "Hexel"},
|
||||
"description": "Create your own cryptocurrency",
|
||||
"dapp-url": {"en" : "https://www.onhexel.com/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://hexel"
|
||||
},
|
||||
|
@ -178,7 +165,6 @@
|
|||
"name" : {"en" : "Kyber"},
|
||||
"description": "On-chain, instant and liquid platform for exchange and payment service",
|
||||
"dapp-url": {"en" : "https://web3.kyber.network"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://kyber"
|
||||
},
|
||||
|
@ -186,7 +172,6 @@
|
|||
"name" : {"en" : "Bancor"},
|
||||
"description": "Bancor is a decentralized liquidity network",
|
||||
"dapp-url": {"en" : "https://www.bancor.network/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://bancor"
|
||||
},
|
||||
|
@ -194,7 +179,6 @@
|
|||
"name" : {"en" : "OpenSea"},
|
||||
"description": "The largest decentralized marketplace for cryptogoods",
|
||||
"dapp-url": {"en" : "https://opensea.io"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://opensea"
|
||||
},
|
||||
|
@ -202,7 +186,6 @@
|
|||
"name" : {"en" : "Decentraland"},
|
||||
"description": "Decentraland is a virtual reality platform powered by the Ethereum blockchain.",
|
||||
"dapp-url": {"en" : "https://market.decentraland.org/"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://decentraland"
|
||||
},
|
||||
|
@ -210,7 +193,6 @@
|
|||
"name" : {"en" : "CryptoCribs"},
|
||||
"description": "Travel the globe. Pay in crypto.",
|
||||
"dapp-url": {"en" : "https://cryptocribs.com"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://cryptocribs"
|
||||
},
|
||||
|
@ -218,7 +200,6 @@
|
|||
"name" : {"en" : "CryptoFighters"},
|
||||
"description": "Collect train and fight digital fighters.",
|
||||
"dapp-url": {"en" : "https://cryptofighters.io"},
|
||||
"groups": ["dapps"],
|
||||
"dapp?": true,
|
||||
"photo-path": "contacts://cryptofighters"
|
||||
}
|
||||
|
|
|
@ -26,9 +26,7 @@
|
|||
:unremovable? true
|
||||
:timestamp (.getTime (js/Date.))
|
||||
:photo-path (str "contacts://" constants/console-chat-id)
|
||||
:contacts [{:identity constants/console-chat-id
|
||||
:text-color "#FFFFFF"
|
||||
:background-color "#AB7967"}]
|
||||
:contacts [constants/console-chat-id]
|
||||
:last-clock-value 0})
|
||||
|
||||
(def contact
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
[status-im.chat.models :as models]
|
||||
[status-im.chat.console :as console]
|
||||
[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.screens.navigation :as navigation]
|
||||
[status-im.ui.screens.group.events :as group.events]
|
||||
[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.public-chat :as public-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]))})))
|
||||
|
||||
(defn init-console-chat
|
||||
[{:keys [chats] :as db}]
|
||||
(if (chats constants/console-chat-id)
|
||||
{:db db}
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-not (get-in db [:chats constants/console-chat-id])
|
||||
{:db (-> db
|
||||
(assoc :current-chat-id constants/console-chat-id)
|
||||
(update :chats assoc constants/console-chat-id console/chat))
|
||||
:dispatch [:add-contacts [console/contact]]
|
||||
:data-store/save-chat console/chat
|
||||
:data-store/save-contact console/contact}))
|
||||
:data-store/save-chat console/chat}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:init-console-chat
|
||||
(fn [{:keys [db]} _]
|
||||
(init-console-chat db)))
|
||||
(defn- add-default-contacts
|
||||
[{:keys [db default-contacts] :as cofx}]
|
||||
(let [new-contacts (-> {}
|
||||
(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
|
||||
: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/get-messages)
|
||||
(re-frame/inject-cofx :data-store/unviewed-messages)
|
||||
(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
|
||||
all-stored-chats
|
||||
inactive-chat-ids
|
||||
stored-unanswered-requests
|
||||
get-stored-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}]
|
||||
(assoc-in acc [chat-id message-id] request))
|
||||
{}
|
||||
|
@ -126,11 +151,13 @@
|
|||
(-> chat-messages keys set))))))
|
||||
{}
|
||||
all-stored-chats)]
|
||||
(-> db
|
||||
(assoc :chats chats
|
||||
:deleted-chats inactive-chat-ids)
|
||||
init-console-chat
|
||||
(update :dispatch-n conj [:load-default-contacts!])))))
|
||||
(handlers/merge-fx cofx
|
||||
{:db (assoc db
|
||||
:chats chats
|
||||
:deleted-chats inactive-chat-ids)}
|
||||
(init-console-chat)
|
||||
(group.events/add-default-groups)
|
||||
(add-default-contacts)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:browse-link-from-message
|
||||
|
@ -147,7 +174,7 @@
|
|||
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}]
|
||||
(when (and (seq message-ids)
|
||||
(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
|
||||
(defn- mark-messages-seen
|
||||
|
@ -254,11 +281,20 @@
|
|||
(fn [cofx [chat]]
|
||||
(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
|
||||
:remove-chat
|
||||
[re-frame/trim-v]
|
||||
(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
|
||||
:remove-chat-and-navigate-home
|
||||
|
@ -266,6 +302,7 @@
|
|||
(fn [cofx [chat-id]]
|
||||
(handlers/merge-fx cofx
|
||||
(models/remove-chat chat-id)
|
||||
(remove-transport chat-id)
|
||||
(navigation/replace-view :home))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
|
@ -312,28 +349,16 @@
|
|||
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
|
||||
(navigation/navigate-to-clean :home)
|
||||
(navigate-to-chat random-id {})
|
||||
(transport/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)))))
|
||||
(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:leave-group-chat?
|
||||
(fn [_ _]
|
||||
[re-frame/trim-v]
|
||||
(fn [_ [chat-id]]
|
||||
{:show-confirmation {:title (i18n/label :t/leave-confirmation)
|
||||
:content (i18n/label :t/leave-group-chat-confirmation)
|
||||
: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
|
||||
:show-profile
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
(ns status-im.chat.models
|
||||
(:require [status-im.ui.components.styles :as styles]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.transport.core :as transport]))
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
|
||||
(defn set-chat-ui-props
|
||||
"Updates ui-props in active chat by merging provided kvs into them"
|
||||
|
@ -23,7 +22,7 @@
|
|||
:group-chat false
|
||||
:is-active true
|
||||
:timestamp now
|
||||
:contacts [{:identity chat-id}]
|
||||
:contacts [chat-id]
|
||||
:last-clock-value 0}))
|
||||
|
||||
(defn add-chat
|
||||
|
@ -65,7 +64,7 @@
|
|||
:group-admin admin
|
||||
:is-active true
|
||||
:timestamp now
|
||||
:contacts (mapv (partial hash-map :identity) participants)
|
||||
:contacts participants
|
||||
:last-clock-value 0}]
|
||||
{:db (assoc-in db [:chats chat-id] chat)
|
||||
:data-store/save-chat chat}))
|
||||
|
@ -98,8 +97,8 @@
|
|||
(> timestamp removed-from-at)))
|
||||
|
||||
(defn remove-chat [chat-id {:keys [db] :as cofx}]
|
||||
(let [{:keys [chat-id group-chat debug?]} (get-in db [:chats chat-id])
|
||||
fx (cond-> {:db (-> db
|
||||
(let [{:keys [chat-id group-chat debug?]} (get-in db [:chats chat-id])]
|
||||
(cond-> {:db (-> db
|
||||
(update :chats dissoc chat-id)
|
||||
(update :deleted-chats (fnil conj #{}) chat-id))}
|
||||
(or group-chat debug?)
|
||||
|
@ -107,8 +106,7 @@
|
|||
debug?
|
||||
(assoc :data-store/delete-chat chat-id)
|
||||
(not debug?)
|
||||
(assoc :data-store/deactivate-chat chat-id))]
|
||||
(handlers/merge-fx cofx fx (transport/unsubscribe-from-chat chat-id))))
|
||||
(assoc :data-store/deactivate-chat chat-id))))
|
||||
|
||||
(defn bot-only-chat? [db chat-id]
|
||||
(let [{:keys [group-chat contacts]} (get-in db [:chats chat-id])]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{}
|
||||
name->ref))
|
||||
|
||||
(defn- is-dapp? [all-contacts {:keys [identity]}]
|
||||
(defn- is-dapp? [all-contacts identity]
|
||||
(get-in all-contacts [identity :dapp?]))
|
||||
|
||||
(defn command-name [{:keys [name]}]
|
||||
|
@ -30,8 +30,7 @@
|
|||
humans? (conj :humans)
|
||||
public? (conj :public-chats))
|
||||
global-access-scope (conj basic-access-scope :global)
|
||||
member-access-scopes (into #{} (map (comp (partial conj basic-access-scope) :identity))
|
||||
contacts)]
|
||||
member-access-scopes (into #{} (map (partial conj basic-access-scope)) contacts)]
|
||||
(reduce (fn [acc access-scope]
|
||||
(merge acc (resolve-references all-contacts
|
||||
(get-in access-scope->commands-responses [access-scope type]))))
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
: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))
|
||||
|
||||
|
|
|
@ -46,14 +46,10 @@
|
|||
{::evaluate-jail-n [{:jail-id whisper-identity
|
||||
:jail-resource commands-snippet}]}))
|
||||
|
||||
(defn load-commands
|
||||
"This function takes coeffects, effects and contact and adds effects
|
||||
for loading all commands/responses/subscriptions.
|
||||
|
||||
It's currently working only for bots, eq we are not evaluating
|
||||
dapp resources in jail at all."
|
||||
(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 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
|
||||
|
@ -61,8 +57,20 @@
|
|||
: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))
|
||||
[::proceed-loading whisper-identity {:error error-response}])})))
|
||||
|
||||
(defn load-commands
|
||||
"This function takes coeffects and produces effects
|
||||
for loading all commands/responses/subscriptions for existing bot contacts.
|
||||
|
||||
It's currently working only for bots, eq we are not evaluating
|
||||
dapp resources in jail at all."
|
||||
[{:keys [db] :as cofx}]
|
||||
(transduce (comp (map second)
|
||||
(filter :bot-url))
|
||||
(completing (partial load-commands-for-bot cofx))
|
||||
{}
|
||||
(:contacts/contacts db)))
|
||||
|
||||
(defn- add-exclusive-choices [initial-scope exclusive-choices]
|
||||
(reduce (fn [scopes-set exclusive-choices]
|
||||
|
|
|
@ -179,4 +179,4 @@
|
|||
::load-commands
|
||||
[re-frame/trim-v (re-frame/inject-cofx :data-store/get-local-storage-data)]
|
||||
(fn [cofx [contact]]
|
||||
(loading-events/load-commands cofx {} contact)))
|
||||
(loading-events/load-commands-for-bot cofx {} contact)))
|
||||
|
|
|
@ -74,41 +74,23 @@
|
|||
(aset "is-active" false)
|
||||
(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
|
||||
[chat-id identities]
|
||||
(let [contacts (get-contacts chat-id)
|
||||
added-at (datetime/timestamp)]
|
||||
(let [chat (get-by-id-obj chat-id)
|
||||
contacts (object/get chat "contacts")]
|
||||
(realm/write @realm/account-realm
|
||||
#(save-contacts identities contacts added-at))))
|
||||
|
||||
(defn- delete-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))))
|
||||
#(aset chat "contacts"
|
||||
(clj->js (into #{} (concat identities
|
||||
(realm/js-object->clj contacts))))))))
|
||||
|
||||
(defn remove-contacts
|
||||
[chat-id identities]
|
||||
(let [contacts (get-contacts chat-id)]
|
||||
(delete-contacts identities contacts)))
|
||||
(let [chat (get-by-id-obj chat-id)
|
||||
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
|
||||
[chat-id property-name value]
|
||||
|
|
|
@ -33,21 +33,15 @@
|
|||
(when-let [group (realm/get-one-by-field @realm/account-realm :contact-group :group-id group-id)]
|
||||
(realm/delete @realm/account-realm group)))
|
||||
|
||||
(defn get-contacts
|
||||
(defn- get-by-id-obj
|
||||
[group-id]
|
||||
(-> @realm/account-realm
|
||||
(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})))))
|
||||
(realm/get-one-by-field @realm/account-realm :contact-group :group-id group-id))
|
||||
|
||||
(defn add-contacts
|
||||
[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
|
||||
#(save-contacts identities contacts))))
|
||||
#(aset group "contacts"
|
||||
(clj->js (into #{} (concat identities
|
||||
(realm/js-object->clj contacts))))))))
|
||||
|
|
|
@ -13,10 +13,7 @@
|
|||
:optional true}
|
||||
:is-active :bool
|
||||
:timestamp :int
|
||||
:contacts {:type :list
|
||||
:objectType :chat-contact}
|
||||
:unremovable? {:type :bool
|
||||
:default false}
|
||||
:contacts {:type "string[]"}
|
||||
:removed-at {:type :int
|
||||
:optional true}
|
||||
:removed-from-at {:type :int
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
:name :string
|
||||
:timestamp :int
|
||||
:order :int
|
||||
:pending? {:type :bool :default false}
|
||||
:contacts {:type :list
|
||||
:objectType :group-contact}}})
|
||||
:contacts {:type "string[]"}}})
|
||||
|
||||
(defn migration [old-realm new-realm]
|
||||
(log/debug "migrating group schema v1"))
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v1.core
|
||||
(: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.chat-contact :as chat-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.request :as request]
|
||||
[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.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.browser :as browser]
|
||||
[goog.object :as object]
|
||||
|
@ -16,14 +14,12 @@
|
|||
[clojure.string :as string]))
|
||||
|
||||
(def schema [chat/schema
|
||||
chat-contact/schema
|
||||
transport/schema
|
||||
contact/schema
|
||||
message/schema
|
||||
request/schema
|
||||
user-status/schema
|
||||
contact-group/schema
|
||||
group-contact/schema
|
||||
local-storage/schema
|
||||
browser/schema])
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
: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]]
|
||||
(let [{:keys [payload sig]} (js->clj js-message :keywordize-keys true)
|
||||
status-message (-> payload
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
(defrecord NewGroupKey [chat-id sym-key message]
|
||||
message/StatusMessage
|
||||
(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
|
||||
:chat-id chat-id
|
||||
:payload this}
|
||||
|
@ -32,6 +32,7 @@
|
|||
:sym-key sym-key
|
||||
:on-success (fn [sym-key sym-key-id]
|
||||
(re-frame/dispatch [::add-new-sym-key {:chat-id chat-id
|
||||
:signature signature
|
||||
:sym-key sym-key
|
||||
:sym-key-id sym-key-id
|
||||
:message message}]))}}
|
||||
|
@ -80,20 +81,20 @@
|
|||
(handlers/merge-fx cofx
|
||||
(init-chat-if-new 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)]
|
||||
;; 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])]
|
||||
;; 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))
|
||||
admin-name (or (get-in cofx [db :contacts/contacts group-admin :name])
|
||||
group-admin)
|
||||
message-id (transport.utils/message-id this)]
|
||||
group-admin)]
|
||||
(if (removed me) ;; we were removed
|
||||
(handlers/merge-fx cofx
|
||||
(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))))
|
||||
(models.chat/update-chat {:chat-id chat-id
|
||||
:removed-from-at now
|
||||
|
@ -101,7 +102,7 @@
|
|||
(transport/unsubscribe-from-chat chat-id))
|
||||
(handlers/merge-fx cofx
|
||||
(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
|
||||
added
|
||||
removed
|
||||
|
@ -119,15 +120,14 @@
|
|||
:payload this
|
||||
:success-event [::unsubscribe-from-chat chat-id]}
|
||||
cofx))
|
||||
(receive [this chat-id signature {:keys [db now] :as cofx}]
|
||||
(let [message-id (transport.utils/message-id this)
|
||||
me (:current-public-key db)
|
||||
(receive [this chat-id signature {:keys [db now random-id] :as cofx}]
|
||||
(let [me (:current-public-key db)
|
||||
participant-leaving-name (or (get-in db [:contacts/contacts signature :name])
|
||||
signature)]
|
||||
(when-not (= me signature)
|
||||
(when (get-in db [:chats chat-id]) ;; chat is present
|
||||
(handlers/merge-fx cofx
|
||||
(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))))
|
||||
(group/participants-removed chat-id #{signature})
|
||||
(send-new-group-key nil chat-id))))))
|
||||
|
@ -160,8 +160,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
::add-new-sym-key
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db] :as cofx} [{:keys [sym-key-id sym-key chat-id message]}]]
|
||||
[re-frame/trim-v (re-frame/inject-cofx :random-id)]
|
||||
(fn [{:keys [db] :as cofx} [{:keys [sym-key-id sym-key chat-id signature message]}]]
|
||||
(let [{:keys [web3 current-public-key]} db
|
||||
fx {:db (assoc-in db [:transport/chats chat-id :sym-key-id] sym-key-id)
|
||||
:shh/add-filter {:web3 web3
|
||||
|
@ -175,5 +175,5 @@
|
|||
(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 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))))
|
||||
|
|
|
@ -63,11 +63,17 @@
|
|||
|
||||
(defn- prepare-recipients [public-keys db]
|
||||
(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))
|
||||
|
||||
(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}]
|
||||
(let [{:keys [current-public-key web3]} db
|
||||
recipients (prepare-recipients public-keys db)]
|
||||
|
|
|
@ -82,11 +82,11 @@
|
|||
:or {error-event :protocol/send-status-message-error}}]
|
||||
(let [whisper-message (update message :payload (comp transport.utils/from-utf8
|
||||
transit/serialize))]
|
||||
(doseq [{:keys [sym-key-id topic]} recipients]
|
||||
(doseq [{:keys [sym-key-id pub-key topic]} recipients]
|
||||
(post-message {:web3 web3
|
||||
:whisper-message (assoc whisper-message
|
||||
:symKeyID sym-key-id
|
||||
:topic topic)
|
||||
:whisper-message (cond-> (assoc whisper-message :topic topic)
|
||||
sym-key-id (assoc :symKeyID sym-key-id)
|
||||
pub-key (assoc :pubKey pub-key))
|
||||
:on-success (if success-event
|
||||
#(re-frame/dispatch success-event)
|
||||
#(log/debug :shh/post-success))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
:on-press #(re-frame/dispatch [:navigate-to :new-chat])}]
|
||||
[action-button/action-separator]
|
||||
;; 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)
|
||||
:accessibility-label :start-group-chat-button
|
||||
:icon :icons/contacts
|
||||
|
|
|
@ -1,36 +1,22 @@
|
|||
(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]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.contacts :as utils.contacts]
|
||||
[status-im.utils.random :as random]
|
||||
[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.constants :as constants]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.utils.gfycat.core :as gfycat.core]
|
||||
[status-im.ui.screens.contacts.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.events :as chat.events]
|
||||
[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.v1.contact :as message.v1.contact]
|
||||
[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
|
||||
|
||||
(defn- update-contact [{:keys [whisper-identity] :as contact} {:keys [db]}]
|
||||
|
@ -38,84 +24,6 @@
|
|||
{:db (update-in db [:contacts/contacts whisper-identity] merge 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
|
||||
:load-contacts
|
||||
[(re-frame/inject-cofx :data-store/get-all-contacts)]
|
||||
|
@ -124,24 +32,6 @@
|
|||
contacts (into {} contacts-list)]
|
||||
{: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]}]
|
||||
(let [new-contact (assoc contact :pending? false)]
|
||||
{:db (-> db
|
||||
|
@ -168,7 +58,7 @@
|
|||
(reader/read-string contact-info)
|
||||
(or (get contacts 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}]
|
||||
(let [contact (build-contact whisper-id cofx)]
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
(remove #(true? (:dapp? %)) 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)))
|
||||
|
||||
(reg-sub :group-contacts
|
||||
|
@ -59,7 +59,7 @@
|
|||
(filter-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)))
|
||||
|
||||
(reg-sub :all-not-added-group-contacts
|
||||
|
@ -123,10 +123,7 @@
|
|||
|
||||
(defn chat-contacts [[chat contacts] [_ fn]]
|
||||
(when chat
|
||||
(let [current-participants (->> chat
|
||||
:contacts
|
||||
(map :identity)
|
||||
set)]
|
||||
(let [current-participants (-> chat :contacts set)]
|
||||
(fn #(current-participants (:whisper-identity %))
|
||||
(vals contacts)))))
|
||||
|
||||
|
|
|
@ -275,10 +275,10 @@
|
|||
{:dispatch-n (cond-> [[:initialize-account-db address]
|
||||
[:initialize-protocol address]
|
||||
[:initialize-sync-listener]
|
||||
[:initialize-chats]
|
||||
[:initialize-browsers]
|
||||
[:load-contacts]
|
||||
[:load-contact-groups]
|
||||
[:initialize-chats]
|
||||
[:initialize-browsers]
|
||||
[:initialize-debugging {:address address}]
|
||||
[:send-account-update-if-needed]
|
||||
[:update-wallet]
|
||||
|
|
|
@ -20,9 +20,7 @@
|
|||
:add-new-group-chat-participants
|
||||
[(re-frame/inject-cofx :random-id)]
|
||||
(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)
|
||||
participants (concat (get-in db [:chats current-chat-id :contacts])
|
||||
selected-participants)
|
||||
(let [participants (concat (get-in db [:chats current-chat-id :contacts]) selected-participants)
|
||||
contacts (:contacts/contacts db)
|
||||
added-participants-names (map #(get-in contacts [% :name]) selected-participants)]
|
||||
(handlers/merge-fx cofx
|
||||
|
@ -39,8 +37,7 @@
|
|||
:remove-group-chat-participants
|
||||
[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]]
|
||||
(let [participants (remove #(removed-participants (:identity %))
|
||||
(get-in db [:chats current-chat-id :contacts]))
|
||||
(let [participants (remove removed-participants (get-in db [:chats current-chat-id :contacts]))
|
||||
contacts (:contacts/contacts db)
|
||||
removed-participants-names (map #(get-in contacts [% :name]) removed-participants)]
|
||||
(handlers/merge-fx cofx
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
(defn participants-added [chat-id added-participants-set {:keys [db] :as cofx}]
|
||||
(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]}))
|
||||
|
||||
(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])]
|
||||
;;TODO: not sure what this condition is for
|
||||
(when (and is-active (>= now timestamp))
|
||||
{:db (update-in db [:chats chat-id :contacts]
|
||||
(partial remove (comp removed-participants-set :identity)))
|
||||
{:db (update-in db [:chats chat-id :contacts] (partial remove removed-participants-set))
|
||||
:data-store/remove-chat-contacts [chat-id removed-participants-set]}))))
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
(spec/def :group/pending? boolean?)
|
||||
(spec/def :group/order int?)
|
||||
|
||||
(spec/def :group-contact/identity :global/not-empty-string)
|
||||
|
||||
(spec/def :group/contact (allowed-keys :req-un [:group-contact/identity]))
|
||||
(spec/def :group/contact :global/not-empty-string)
|
||||
|
||||
(spec/def :group/contacts (spec/nilable (spec/* :group/contact)))
|
||||
|
||||
|
|
|
@ -1,109 +1,77 @@
|
|||
(ns status-im.ui.screens.group.events
|
||||
(:require [re-frame.core :refer [dispatch reg-fx reg-cofx inject-cofx]]
|
||||
[status-im.utils.handlers :refer [register-handler-db register-handler-fx]]
|
||||
[status-im.ui.components.styles :refer [default-chat-color]]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.ui.screens.group.navigation]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[re-frame.core :as re-frame]))
|
||||
(:require [clojure.set :as set]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.js-resources :as js-res]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.ui.screens.group.navigation]))
|
||||
|
||||
;;;; 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
|
||||
|
||||
(register-handler-db
|
||||
(handlers/register-handler-db
|
||||
:deselect-contact
|
||||
(fn [db [_ id]]
|
||||
(update db :group/selected-contacts disj id)))
|
||||
|
||||
(register-handler-db
|
||||
(handlers/register-handler-db
|
||||
:select-contact
|
||||
(fn [db [_ id]]
|
||||
(update db :group/selected-contacts conj id)))
|
||||
|
||||
(register-handler-db
|
||||
(handlers/register-handler-db
|
||||
:deselect-participant
|
||||
(fn [db [_ id]]
|
||||
(update db :selected-participants disj id)))
|
||||
|
||||
(register-handler-db
|
||||
(handlers/register-handler-db
|
||||
:select-participant
|
||||
(fn [db [_ id]]
|
||||
(update db :selected-participants conj id)))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:create-new-contact-group
|
||||
[(re-frame/inject-cofx :now)]
|
||||
(fn [{{:group/keys [contact-groups selected-contacts] :as db} :db
|
||||
now :now} [_ group-name]]
|
||||
(let [selected-contacts' (mapv #(hash-map :identity %) selected-contacts)
|
||||
new-group {:group-id (random/id)
|
||||
[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 group-id :random-id now :now} [group-name]]
|
||||
(let [new-group {:group-id group-id
|
||||
:name group-name
|
||||
:order (count contact-groups)
|
||||
:timestamp now
|
||||
:contacts selected-contacts'}]
|
||||
{:db (update db :group/contact-groups merge {(:group-id new-group) new-group})
|
||||
:contacts selected-contacts}]
|
||||
{:db (assoc-in db [:group/contact-groups group-id] new-group)
|
||||
:data-store/save-contact-group new-group})))
|
||||
|
||||
(register-handler-fx
|
||||
::update-contact-group
|
||||
(fn [{:keys [db]} [_ new-group]]
|
||||
{:db (update db :group/contact-groups merge {(:group-id new-group) new-group})
|
||||
:data-store/save-contact-group new-group}))
|
||||
(defn add-default-groups
|
||||
[{:keys [db now default-groups]}]
|
||||
(let [new-groups (into {}
|
||||
(map (fn [[id props]]
|
||||
(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}]
|
||||
(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
|
||||
(handlers/register-handler-fx
|
||||
: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]} _]
|
||||
{:db (assoc db :group/contact-groups all-contact-groups)}))
|
||||
|
||||
(defn move-item [v from to]
|
||||
(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
|
||||
(handlers/register-handler-fx
|
||||
:set-contact-group-name
|
||||
(fn [{{:keys [new-chat-name] :group/keys [contact-group-id] :as db} :db} _]
|
||||
{:db (assoc-in db
|
||||
|
@ -111,37 +79,20 @@
|
|||
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
|
||||
(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
|
||||
[:group/contact-groups contact-group-id :contacts]
|
||||
#(into [] (set (concat % new-identities))))
|
||||
:data-store/add-contacts-to-contact-group [contact-group-id selected-contacts]})))
|
||||
#(into [] (set (concat % selected-contacts))))
|
||||
:data-store/add-contacts-to-contact-group [contact-group-id selected-contacts]}))
|
||||
|
||||
(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
|
||||
(handlers/register-handler-fx
|
||||
:remove-contact-from-group
|
||||
(fn [{:keys [db]} [_ whisper-identity group-id]]
|
||||
(let [{:group/keys [contact-groups]} db
|
||||
group' (update (contact-groups group-id) :contacts (remove-contact-from-group whisper-identity))]
|
||||
{:dispatch [::update-contact-group group']})))
|
||||
|
||||
(register-handler-fx
|
||||
:delete-contact-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]}))
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [whisper-identity group-id]]
|
||||
(let [group (-> db
|
||||
(get-in [:group/contact-groups group-id])
|
||||
(update :contacts (partial remove #(= whisper-identity %))))]
|
||||
{:db (assoc-in db [:group/contact-groups group-id] group)
|
||||
:data-store/save-contact-group group})))
|
||||
|
|
|
@ -38,9 +38,7 @@
|
|||
|
||||
(defn actions [admin? chat-id]
|
||||
(concat
|
||||
;; NOTE(goranjovic) - group chat participant removal has been temporarily disabled
|
||||
;; due to this bug - https://github.com/status-im/status-react/issues/3463
|
||||
#_(when admin?
|
||||
(when admin?
|
||||
[{:label (i18n/label :add-members)
|
||||
:icon :icons/add
|
||||
:action #(re-frame/dispatch [:navigate-to :add-participants-toggle-list])}])
|
||||
|
@ -64,15 +62,13 @@
|
|||
:action #(utils/show-confirmation (i18n/label :t/leave-group-title)
|
||||
(i18n/label :t/leave-group-confirmation)
|
||||
(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}]))
|
||||
|
||||
(defn contact-actions [contact]
|
||||
[{:action #(re-frame/dispatch [:show-profile (:whisper-identity contact)])
|
||||
:label (i18n/label :t/view-profile)}
|
||||
;; NOTE(goranjovic) - group chat participant removal has been temporarily disabled
|
||||
;; due to this bug - https://github.com/status-im/status-react/issues/3463
|
||||
#_{:action #(re-frame/dispatch [:remove-group-chat-participants #{(:whisper-identity contact)}])
|
||||
{:action #(re-frame/dispatch [:remove-group-chat-participants #{(:whisper-identity contact)}])
|
||||
:label (i18n/label :t/remove-from-chat)}])
|
||||
|
||||
(defn render-contact [contact admin?]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.utils.contacts
|
||||
(:require
|
||||
(:require [status-im.js-dependencies :as js-dependencies]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.utils.gfycat.core :as gfycat]))
|
||||
|
||||
|
@ -7,3 +7,13 @@
|
|||
{:name (gfycat/generate-gfy whisper-id)
|
||||
:photo-path (identicon/identicon 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))))
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
(deftest init-console-chat
|
||||
(testing "initialising console if console is already added to chats, should not modify anything"
|
||||
(let [db {:chats {const/console-chat-id console-chat/chat}}
|
||||
fx (chat-events/init-console-chat db)]
|
||||
(is (= db (:db fx)))
|
||||
(is (= #{:db} (-> fx keys set)))))
|
||||
fx (chat-events/init-console-chat {:db db})]
|
||||
(is (not fx))))
|
||||
|
||||
(testing "initialising console without existing account and console chat not initialisated"
|
||||
(let [fresh-db {:chats {}
|
||||
: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)
|
||||
(:chat-id console-chat/chat)))
|
||||
(is (= (:current-chat-id db)
|
||||
|
@ -33,7 +32,7 @@
|
|||
(testing "initialising console with existing account and console chat not initialisated"
|
||||
(let [fresh-db {:chats {}
|
||||
: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)
|
||||
(:chat-id console-chat/chat)))
|
||||
(is (= (:current-chat-id db)
|
||||
|
|
|
@ -8,19 +8,17 @@
|
|||
#{"0x1" :group-chats :anonymous :dapps} {:command {"command2" ["0x1" :command 4 "command2"]}}
|
||||
#{"0x2" :personal-chats :anonymous :dapps} {:command {"command3" ["0x2" :command 2 "command3"]}}
|
||||
#{"0x2" :group-chats :anonymous :dapps} {:response {"response1" ["0x2" :response 4 "response1"]}}}
|
||||
:chats {"test1" {:contacts [{:identity "0x1"}]
|
||||
:chats {"test1" {:contacts ["0x1"]
|
||||
:requests nil
|
||||
:seq-arguments ["arg1" "arg2"]}
|
||||
"test2" {:contacts [{:identity "0x1"}
|
||||
{:identity "0x2"}]
|
||||
"test2" {:contacts ["0x1" "0x2"]
|
||||
:group-chat true
|
||||
:requests {"id1" {:message-id "id1"
|
||||
:response "response1"}}}
|
||||
"test3" {:contacts [{:identity "0x1"}]
|
||||
"test3" {:contacts ["0x1"]
|
||||
:requests {"id1" {:message-id "id1"
|
||||
:response "request1"}}}
|
||||
"test4" {:contacts [{:identity "0x1"}
|
||||
{:identity "0x2"}]
|
||||
"test4" {:contacts ["0x1" "0x2"]
|
||||
:group-chat true
|
||||
:requests {"id2" {:message-id "id2"
|
||||
:response "response1"}}
|
||||
|
|
Loading…
Reference in New Issue