Julien Eluard 33f1d8d26b
[ISSUE #3313] Migrated public chat creation flow
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
2018-02-22 12:22:08 +01:00

192 lines
7.9 KiB
Clojure

(ns status-im.chat.handlers
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.chat.models :as models]
[status-im.i18n :as i18n]
[status-im.protocol.core :as protocol]
[status-im.ui.components.styles :as components.styles]
[status-im.utils.handlers :as handlers]
[status-im.utils.random :as random]
status-im.chat.events))
(handlers/register-handler
:leave-group-chat
;; todo order of operations tbd
(re-frame/after (fn [_ _] (re-frame/dispatch [:navigation-replace :home])))
(handlers/side-effect!
(fn [{:keys [web3 current-chat-id chats current-public-key]} _]
(let [{:keys [public-key private-key public?]} (chats current-chat-id)]
(protocol/stop-watching-group!
{:web3 web3
:group-id current-chat-id})
(when-not public?
(protocol/leave-group-chat!
{:web3 web3
:group-id current-chat-id
:keypair {:public public-key
:private private-key}
:message {:from current-public-key
:message-id (random/id)}})))
(re-frame/dispatch [:remove-chat current-chat-id]))))
(handlers/register-handler-fx
:leave-group-chat?
(fn []
{: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])}}))
(handlers/register-handler :update-group-message
(handlers/side-effect!
(fn [{:keys [current-public-key web3 chats]}
[_ {:keys [from]
{:keys [group-id keypair timestamp]} :payload}]]
(let [{:keys [private public]} keypair
{:keys [group-admin is-active] :as chat} (get chats group-id)]
(when (and (= from group-admin
(or (nil? chat)
(models/new-update? chat timestamp))))
(re-frame/dispatch [:update-chat! {:chat-id group-id
:public-key public
:private-key private
:updated-at timestamp}])
(when is-active
(protocol/start-watching-group!
{:web3 web3
:group-id group-id
:identity current-public-key
:keypair keypair
:callback #(re-frame/dispatch [:incoming-message %1 %2])})))))))
(re-frame/reg-fx
::start-watching-group
(fn [{:keys [group-id web3 current-public-key keypair]}]
(protocol/start-watching-group!
{:web3 web3
:group-id group-id
:identity current-public-key
:keypair keypair
:callback #(re-frame/dispatch [:incoming-message %1 %2])})))
(handlers/register-handler-fx
:create-new-public-chat
(fn [{:keys [db]} [_ topic]]
(let [exists? (boolean (get-in db [:chats topic]))
chat {:chat-id topic
:name topic
:color components.styles/default-chat-color
:group-chat true
:public? true
:is-active true
:timestamp (random/timestamp)}]
(merge
(when-not exists?
{:db (assoc-in db [:chats (:chat-id chat)] chat)
:save-chat chat
::start-watching-group (merge {:group-id topic}
(select-keys db [:web3 :current-public-key]))})
{:dispatch-n [[:navigate-to-clean :home]
[:navigate-to-chat topic]]}))))
(re-frame/reg-fx
::start-listen-group
(fn [{:keys [new-chat web3 current-public-key]}]
(let [{:keys [chat-id public-key private-key contacts name]} new-chat
identities (mapv :identity contacts)]
(protocol/invite-to-group!
{:web3 web3
:group {:id chat-id
:name name
:contacts (conj identities current-public-key)
:admin current-public-key
:keypair {:public public-key
:private private-key}}
:identities identities
:message {:from current-public-key
:message-id (random/id)}})
(protocol/start-watching-group!
{:web3 web3
:group-id chat-id
:identity current-public-key
:keypair {:public public-key
:private private-key}
:callback #(re-frame/dispatch [:incoming-message %1 %2])}))))
(defn group-name-from-contacts [contacts selected-contacts username]
(->> (select-keys contacts selected-contacts)
vals
(map :name)
(cons username)
(string/join ", ")))
(defn prepare-group-chat
[{:keys [current-public-key username]
:group/keys [selected-contacts]
:contacts/keys [contacts]} group-name]
(let [selected-contacts' (mapv #(hash-map :identity %) selected-contacts)
chat-name (if-not (string/blank? group-name)
group-name
(group-name-from-contacts contacts selected-contacts username))
{:keys [public private]} (protocol/new-keypair!)]
{:chat-id (random/id)
:public-key public
:private-key private
:name chat-name
:color components.styles/default-chat-color
:group-chat true
:group-admin current-public-key
:is-active true
:timestamp (random/timestamp)
:contacts selected-contacts'}))
(handlers/register-handler-fx
:create-new-group-chat-and-open
(fn [{:keys [db]} [_ group-name]]
(let [new-chat (prepare-group-chat (select-keys db [:group/selected-contacts :current-public-key :username
:contacts/contacts])
group-name)]
{:db (-> db
(assoc-in [:chats (:chat-id new-chat)] new-chat)
(assoc :group/selected-contacts #{}))
:save-chat new-chat
::start-listen-group (merge {:new-chat new-chat}
(select-keys db [:web3 :current-public-key]))
:dispatch-n [[:navigate-to-clean :home]
[:navigate-to-chat (:chat-id new-chat)]]})))
(handlers/register-handler-fx
:group-chat-invite-received
(fn [{{:keys [current-public-key] :as db} :db}
[_ {:keys [from]
{:keys [group-id group-name contacts keypair timestamp]} :payload}]]
(let [{:keys [private public]} keypair]
(let [contacts' (keep (fn [ident]
(when (not= ident current-public-key)
{:identity ident})) contacts)
chat (get-in db [:chats group-id])
new-chat {:chat-id group-id
:name group-name
:group-chat true
:group-admin from
:public-key public
:private-key private
:contacts contacts'
:added-to-at timestamp
:timestamp timestamp
:is-active true}]
(when (or (nil? chat)
(models/new-update? chat timestamp))
{::start-watching-group (merge {:group-id group-id
:keypair keypair}
(select-keys db [:web3 :current-public-key]))
:dispatch (if chat
[:update-chat! new-chat]
[:add-chat group-id new-chat])})))))
(handlers/register-handler-fx
:show-profile
(fn [{db :db} [_ identity]]
{:db (assoc db :contacts/identity identity)
:dispatch [:navigate-forget :profile]}))