Proceed with move from side-effect to functional

This commit is contained in:
janherich 2017-10-06 02:28:59 +02:00 committed by Roman Volosovskyi
parent e9cf3db400
commit d39357996b
13 changed files with 376 additions and 379 deletions

View File

@ -2,6 +2,7 @@
(:require [re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.utils.handlers :as handlers]
[status-im.utils.gfycat.core :as gfycat]
[status-im.chat.models :as model]
[status-im.chat.models.unviewed-messages :as unviewed-messages-model]
[status-im.chat.sign-up :as sign-up]
@ -10,6 +11,7 @@
[status-im.data-store.messages :as msg-store]
[status-im.data-store.contacts :as contacts-store]
[status-im.data-store.chats :as chats-store]
[status-im.ui.screens.navigation :as navigation]
[status-im.protocol.core :as protocol]
[status-im.constants :as const]
[status-im.components.list-selection :as list-selection]
@ -23,34 +25,44 @@
;;;; Coeffects
(re-frame/reg-cofx
:stored-unviewed-messages
(fn [cofx _]
(assoc cofx :stored-unviewed-messages (msg-store/get-unviewed))))
:stored-unviewed-messages
(fn [cofx _]
(assoc cofx :stored-unviewed-messages (msg-store/get-unviewed))))
(re-frame/reg-cofx
:get-stored-message
(fn [cofx _]
(assoc cofx :get-stored-message msg-store/get-by-id)))
:get-stored-message
(fn [cofx _]
(assoc cofx :get-stored-message msg-store/get-by-id)))
(re-frame/reg-cofx
:get-stored-messages
(fn [cofx _]
(assoc cofx :get-stored-messages msg-store/get-by-chat-id)))
:get-stored-messages
(fn [cofx _]
(assoc cofx :get-stored-messages msg-store/get-by-chat-id)))
(re-frame/reg-cofx
:get-last-stored-message
(fn [cofx _]
(assoc cofx :get-last-stored-message msg-store/get-last-message)))
:get-last-stored-message
(fn [cofx _]
(assoc cofx :get-last-stored-message msg-store/get-last-message)))
(re-frame/reg-cofx
:get-message-previews
(fn [cofx _]
(assoc cofx :message-previews (msg-store/get-previews))))
:get-message-previews
(fn [cofx _]
(assoc cofx :message-previews (msg-store/get-previews))))
(re-frame/reg-cofx
:all-stored-chats
(fn [cofx _]
(assoc cofx :all-stored-chats (chats-store/get-all))))
:all-stored-chats
(fn [cofx _]
(assoc cofx :all-stored-chats (chats-store/get-all))))
(re-frame/reg-cofx
:get-stored-chat
(fn [cofx _]
(assoc cofx :get-stored-chat chats-store/get-by-id)))
(re-frame/reg-cofx
:gfy-generator
(fn [cofx _]
(assoc cofx :gfy-generator gfycat/generate-gfy)))
;;;; Effects
@ -84,26 +96,6 @@
(fn [[command link]]
(list-selection/browse command link)))
;;;; Helper fns
(defn init-console-chat
[{:keys [chats] :accounts/keys [current-account-id] :as db} existing-account?]
(if (get chats const/console-chat-id)
{:db db}
(cond-> {:db (-> db
(assoc :new-chat sign-up/console-chat)
(update :chats assoc const/console-chat-id sign-up/console-chat)
(assoc :current-chat-id const/console-chat-id))
:dispatch-n [[:add-contacts [sign-up/console-contact]]]
:save-chat sign-up/console-chat
:save-all-contacts [sign-up/console-contact]}
(not current-account-id)
(update :dispatch-n concat sign-up/intro-events)
existing-account?
(update :dispatch-n concat sign-up/start-signup-events))))
;;;; Handlers
(handlers/register-handler-db
@ -165,6 +157,24 @@
message))
messages)))))
(defn- init-console-chat
[{:keys [chats] :accounts/keys [current-account-id] :as db} existing-account?]
(if (chats const/console-chat-id)
{:db db}
(cond-> {:db (-> db
(assoc :new-chat sign-up/console-chat
:current-chat-id const/console-chat-id)
(update :chats assoc const/console-chat-id sign-up/console-chat))
:dispatch-n [[:add-contacts [sign-up/console-contact]]]
:save-chat sign-up/console-chat
:save-all-contacts [sign-up/console-contact]}
(not current-account-id)
(update :dispatch-n concat sign-up/intro-events)
existing-account?
(update :dispatch-n concat sign-up/start-signup-events))))
(handlers/register-handler-fx
:init-console-chat
(fn [{:keys [db]} _]
@ -248,17 +258,116 @@
(fn [{:keys [get-stored-message]} _]
(when-not (get-stored-message chat-const/move-to-internal-failure-message-id)
{:dispatch sign-up/move-to-internal-failure-event})))
(comment
(handlers/register-handler-fx
:init-chat
[(re-frame/inject-cofx :get-stored-messages)]
(fn [{:keys [db get-stored-messages]} _]
(let [current-chat-id (:current-chat-id db)]
{:db (assoc-in [:chats current-chat-id :messages] (get-stored-messages current-chat-id))
;; TODO(janherich): make this dispatch into fn call once commands loading is refactored
:dispatch [:load-commands! current-chat-id]}))))
(handlers/register-handler-fx
:browse-link-from-message
(fn [{{:keys [global-commands]} :db} [_ link]]
{:browse [(:browse global-commands) link]}))
(handlers/register-handler-fx
:init-chat
[(re-frame/inject-cofx :get-stored-messages)]
(fn [{:keys [db get-stored-messages]} _]
(let [current-chat-id (:current-chat-id db)]
{:db (assoc-in db [:chats current-chat-id :messages] (get-stored-messages current-chat-id))
;; TODO(janherich): make this dispatch into fn call once commands loading is refactored
:dispatch [:load-commands! current-chat-id]})))
(defn- jail-init-callback
[{:keys [db] :as fx} chat-id]
(let [bot-url (get-in db [:contacts/contacts chat-id :bot-url])
was-opened? (get-in db [:chats chat-id :was-opened?])]
(if (and (not was-opened?) bot-url)
(assoc fx :call-jail-function {:chat-id chat-id
:function :init
:context {:from (:accounts/current-account-id db)}})
fx)))
(defn preload-chat-data
"Takes coeffects map and chat-id, returns effects necessary when navigating to chat"
[{:keys [db get-stored-messages]} chat-id]
(let [messages (get-in db [:chats chat-id :messages])
chat-loaded-event (get-in db [:chats chat-id :chat-loaded-event])
commands-loaded? (get-in db [:contacts/contacts chat-id :commands-loaded?])]
(cond-> {:db (-> db
(assoc :current-chat-id chat-id)
(assoc-in [:chats chat-id :was-opened?] true)
(model/set-chat-ui-props {:validation-messages nil})
(update-in [:chats chat-id] dissoc :chat-loaded-event))
:dispatch-n [[:load-requests! chat-id]]}
(not commands-loaded?)
(update :dispatch-n conj [:load-commands! chat-id #(re-frame/dispatch [::jail-init-callback chat-id])])
commands-loaded?
(jail-init-callback chat-id)
;; TODO(janherich): what's the purpose of the second term in AND ?
(and (seq messages)
(not= (count messages) 1))
(assoc-in [:db :chats chat-id :messages] (get-stored-messages chat-id))
chat-loaded-event
(update :dispatch-n conj chat-loaded-event))))
(handlers/register-handler-db
:add-chat-loaded-event
[re-frame/trim-v]
(fn [db [chat-id event]]
(assoc-in db [:chats chat-id :chat-loaded-event] event)))
(handlers/register-handler-fx
::jail-init-callback
[re-frame/trim-v]
(fn [{:keys [db]} [chat-id]]
(jail-init-callback {:db db} chat-id)))
;; TODO(janherich): remove this unnecessary event in the future (only model function `add-chat` will stay)
(handlers/register-handler-fx
:add-chat
[(re-frame/inject-cofx :gfy-generator) re-frame/trim-v]
(fn [cofx [chat-id]]
(model/add-chat cofx chat-id)))
(defn- navigate-to-chat
[cofx chat-id navigation-replace?]
(let [nav-fn (if navigation-replace?
#(navigation/navigate-to % :chat)
#(navigation/replace-view % :chat))]
(-> cofx
(preload-chat-data chat-id)
(update :db nav-fn))))
(handlers/register-handler-fx
:navigate-to-chat
[(re-frame/inject-cofx :get-stored-messages) re-frame/trim-v]
(fn [cofx [chat-id {:keys [navigation-replace?]}]]
(navigate-to-chat cofx chat-id navigation-replace?)))
(handlers/register-handler-fx
:start-chat
[(re-frame/inject-cofx :gfy-generator)
(re-frame/inject-cofx :get-stored-messages)
re-frame/trim-v]
(fn [{:keys [db] :as cofx} [contact-id {:keys [navigation-replace?]}]]
(when (not= (:current-public-key db) contact-id) ; don't allow to open chat with yourself
(if (get (:chats db) contact-id)
(navigate-to-chat cofx contact-id navigation-replace?) ; existing chat, just preload and displey
(let [add-chat-fx (model/add-chat cofx contact-id)] ; new chat, create before preload & display
(merge add-chat-fx
(navigate-to-chat (assoc cofx :db (:db add-chat-fx))
contact-id
navigation-replace?)))))))
;; TODO(janherich): remove this unnecessary event in the future (only model function `update-chat` will stay)
(handlers/register-handler-fx
:update-chat!
[(re-frame/inject-cofx :get-stored-chat) re-frame/trim-v]
(fn [cofx [chat]]
(model/update-chat cofx chat)))
;; TODO(janherich): remove this unnecessary event in the future (only model function `upsert-chat` will stay)
(handlers/register-handler-fx
:upsert-chat!
[(re-frame/inject-cofx :get-stored-chat) re-frame/trim-v]
(fn [cofx [chat]]
(model/upsert-chat cofx chat)))

View File

@ -6,6 +6,7 @@
[status-im.utils.clocks :as clocks]
[status-im.constants :as const]
[status-im.chat.utils :as chat-utils]
[status-im.chat.models :as model]
[status-im.chat.models.unviewed-messages :as unviewed-messages-model]
[status-im.data-store.chats :as chat-store]
[status-im.data-store.messages :as msg-store]))
@ -33,7 +34,7 @@
(defn add-message
[{:keys [db message-exists? get-last-stored-message pop-up-chat?
get-last-clock-value now random-id]}
get-last-clock-value now random-id] :as cofx}
{:keys [from group-id chat-id content-type
message-id timestamp clock-value]
:as message
@ -54,16 +55,17 @@
:timestamp (or timestamp now)
:clock-value (clocks/receive
clock-value
(get-last-clock-value chat-identifier)))]
(cond-> {:db (-> db
(chat-utils/add-message-to-db chat-identifier chat-identifier enriched-message
(:new? enriched-message))
(unviewed-messages-model/add-unviewed-message chat-identifier message-id)
(assoc-in [:chats chat-identifier :last-message] message))
:dispatch-n [[:upsert-chat! {:chat-id chat-identifier
:group-chat group-chat?}]
[:request-command-message-data enriched-message :short-preview]]
:save-message (dissoc enriched-message :new?)}
(get-last-clock-value chat-identifier)))
fx (model/upsert-chat cofx {:chat-id chat-identifier
:group-chat group-chat?})]
(cond-> (-> fx
(update :db #(-> %
(chat-utils/add-message-to-db chat-identifier chat-identifier enriched-message
(:new? enriched-message))
(unviewed-messages-model/add-unviewed-message chat-identifier message-id)
(assoc-in [:chats chat-identifier :last-message] message)))
(assoc :dispatch-n [[:request-command-message-data enriched-message :short-preview]]
:save-message (dissoc enriched-message :new?)))
(get-in enriched-message [:content :command])
(update :dispatch-n conj [:request-command-preview enriched-message])
@ -78,7 +80,7 @@
(def ^:private receive-interceptors
[(re-frame/inject-cofx :message-exists?) (re-frame/inject-cofx :get-last-stored-message)
(re-frame/inject-cofx :pop-up-chat?) (re-frame/inject-cofx :get-last-clock-value)
(re-frame/inject-cofx :random-id) re-frame/trim-v])
(re-frame/inject-cofx :random-id) (re-frame/inject-cofx :get-stored-chat) re-frame/trim-v])
(handlers/register-handler-fx
:received-protocol-message!

View File

@ -1,186 +1,24 @@
(ns status-im.chat.handlers
(:require-macros [cljs.core.async.macros :as am])
(:require [re-frame.core :refer [enrich after debug dispatch reg-fx]]
[cljs.core.async :as a]
[clojure.string :as string]
[status-im.components.styles :refer [default-chat-color]]
[status-im.chat.constants :as chat-const]
[status-im.components.styles :refer [default-chat-color]]
[status-im.chat.constants :as chat-consts]
[status-im.protocol.core :as protocol]
[status-im.data-store.chats :as chats]
[status-im.data-store.contacts :as contacts]
[status-im.data-store.chats :as chats]
[status-im.data-store.messages :as messages]
[status-im.data-store.pending-messages :as pending-messages]
[status-im.constants :refer [text-content-type
content-type-command
content-type-command-request
console-chat-id]]
[status-im.utils.random :as random]
[status-im.chat.sign-up :as sign-up-service]
[status-im.ui.screens.navigation :as nav]
[status-im.utils.handlers :refer [register-handler register-handler-fx] :as u]
[status-im.utils.phone-number :refer [format-phone-number
valid-mobile-number?]]
[status-im.native-module.core :as status]
[status-im.utils.types :refer [json->clj]]
[status-im.chat.utils :refer [console? not-console? safe-trim]]
[status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.utils.random :as random]
[status-im.utils.handlers :refer [register-handler register-handler-fx] :as u]
status-im.chat.events
status-im.chat.handlers.requests
status-im.chat.handlers.send-message
[cljs.core.async :as a]
status-im.chat.handlers.webview-bridge
[taoensso.timbre :as log]))
(defn load-messages!
([db] (load-messages! db nil))
([{:keys [current-chat-id] :as db} _]
(let [messages (messages/get-by-chat-id current-chat-id)]
(assoc db :messages messages))))
(defn init-chat
([db] (init-chat db nil))
([{:keys [messages current-chat-id] :as db} _]
(-> db
(assoc-in [:chats current-chat-id :messages] messages)
(dissoc :messages))))
(defn load-commands!
[{:keys [current-chat-id]} _]
(dispatch [:load-commands! current-chat-id]))
(register-handler :init-chat
(after #(dispatch [:load-requests!]))
(u/handlers->
load-messages!
init-chat
load-commands!))
(defmethod nav/preload-data! :chat
[{:keys [current-chat-id] :accounts/keys [current-account-id] :as db} [_ _ id]]
(let [chat-id (or id current-chat-id)
messages (get-in db [:chats chat-id :messages])
db' (-> db
(assoc :current-chat-id chat-id)
(assoc-in [:chats chat-id :was-opened?] true))
commands-loaded? (get-in db [:contacts/contacts chat-id :commands-loaded?])
bot-url (get-in db [:contacts/contacts chat-id :bot-url])
was-opened? (get-in db [:chats chat-id :was-opened?])
call-init-command #(do
(dispatch [:invoke-chat-loaded-callbacks chat-id])
(when (and (not was-opened?) bot-url)
(status/call-function!
{:chat-id chat-id
:function :init
:context {:from current-account-id}})))]
; Reset validation messages, if any
(dispatch [:set-chat-ui-props {:validation-messages nil}])
(dispatch [:load-requests! chat-id])
;; todo rewrite this. temporary fix for https://github.com/status-im/status-react/issues/607
#_(dispatch [:load-commands! chat-id])
(if-not commands-loaded?
(dispatch [:load-commands! chat-id call-init-command])
(call-init-command))
(if (and (seq messages)
(not= (count messages) 1))
db'
(-> db'
load-messages!
init-chat))))
(register-handler :add-chat-loaded-callback
(fn [db [_ chat-id callback]]
(log/debug "Add chat loaded callback: " chat-id callback)
(update-in db [:chat-loaded-callbacks chat-id] conj callback)))
(register-handler ::clear-chat-loaded-callbacks
(fn [db [_ chat-id]]
(log/debug "Clear chat loaded callback: " chat-id)
(assoc-in db [:chat-loaded-callbacks chat-id] nil)))
(register-handler :invoke-chat-loaded-callbacks
(u/side-effect!
(fn [db [_ chat-id]]
(log/debug "Invoking chat loaded callbacks: " chat-id)
(let [callbacks (get-in db [:chat-loaded-callbacks chat-id])]
(log/debug "Invoking chat loaded callbacks: " callbacks)
(doseq [callback callbacks]
(callback))
(dispatch [::clear-chat-loaded-callbacks chat-id])))))
(defn prepare-chat [{:contacts/keys [contacts]} chat-id chat]
(let [name (get-in contacts [chat-id :name])
whisper-identity (get-in contacts [chat-id :whisper-identity])]
(merge {:chat-id chat-id
:name (or name (generate-gfy whisper-identity))
:color default-chat-color
:group-chat false
:is-active true
:timestamp (.getTime (js/Date.))
:contacts [{:identity chat-id}]}
chat)))
(defn add-new-chat
[db [_ chat-id chat]]
(assoc db :new-chat (prepare-chat db chat-id chat)))
(defn add-chat [{:keys [new-chat chats] :as db} [_ chat-id]]
(if-not (get chats chat-id)
(update db :chats assoc chat-id new-chat)
db))
(defn save-new-chat!
[{{:keys [chat-id] :as new-chat} :new-chat} _]
(when-not (chats/exists? chat-id)
(chats/save new-chat)))
(defn open-chat!
[_ [_ chat-id _ navigation-type]]
(dispatch [(or navigation-type :navigate-to) :chat chat-id]))
(register-handler ::start-chat!
(u/handlers->
add-new-chat
add-chat
save-new-chat!
open-chat!))
(register-handler :start-chat
(u/side-effect!
(fn [{:keys [chats current-public-key]}
[_ contact-id options navigation-type]]
(when-not (= current-public-key contact-id)
(if (chats contact-id)
(dispatch [(or navigation-type :navigate-to) :chat contact-id])
(dispatch [::start-chat! contact-id options navigation-type]))))))
(register-handler :add-chat
(u/handlers->
add-new-chat
add-chat
save-new-chat!))
(defn update-chat!
[_ [_ {:keys [name] :as chat}]]
(let [chat' (if name chat (dissoc chat :name))]
(chats/save chat')))
(register-handler :update-chat!
(after update-chat!)
(fn [db [_ {:keys [chat-id name] :as chat}]]
(let [chat' (if name chat (dissoc chat :name))]
(if (get-in db [:chats chat-id])
(update-in db [:chats chat-id] merge chat')
db))))
(register-handler :upsert-chat!
(fn [db [_ {:keys [chat-id] :as opts}]]
(let [chat (if (chats/exists? chat-id)
(-> (chats/get-by-id chat-id)
(assoc :timestamp (random/timestamp))
(merge opts))
(prepare-chat db chat-id opts))]
(chats/save chat)
(update-in db [:chats chat-id] merge chat))))
status-im.chat.handlers.send-message
status-im.chat.handlers.webview-bridge))
(defn remove-chat
[db [_ chat-id]]
@ -207,33 +45,36 @@
[_ [_ chat-id]]
(pending-messages/delete-all-by-chat-id chat-id))
(register-handler :leave-group-chat
;; todo oreder of operations tbd
(register-handler
:leave-group-chat
;; todo order of operations tbd
(after (fn [_ _] (dispatch [:navigation-replace :chat-list])))
(u/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!
(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})
(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)}})))
(dispatch [:remove-chat current-chat-id]))))
:group-id current-chat-id
:keypair {:public public-key
:private private-key}
:message {:from current-public-key
:message-id (random/id)}})))
(dispatch [:remove-chat current-chat-id]))))
(register-handler :remove-chat
(register-handler
:remove-chat
(u/handlers->
remove-chat
delete-messages!
remove-pending-messages!
delete-chat!))
remove-chat
delete-messages!
remove-pending-messages!
delete-chat!))
(register-handler :check-and-open-dapp!
(register-handler
:check-and-open-dapp!
(u/side-effect!
(fn [{:keys [current-chat-id global-commands]
:contacts/keys [contacts]}]
@ -249,33 +90,34 @@
(register-handler :update-group-message
(u/side-effect!
(fn [{:keys [current-public-key web3 chats]}
[_ {:keys [from]
{:keys [group-id keypair timestamp]} :payload}]]
(let [{:keys [private public]} keypair]
(let [is-active (chats/is-active? group-id)
chat {:chat-id group-id
:public-key public
:private-key private
:updated-at timestamp}]
(when (and (= from (get-in chats [group-id :group-admin]))
(or (not (chats/exists? group-id))
(chats/new-update? timestamp group-id)))
(dispatch [:update-chat! chat])
(when is-active
(protocol/start-watching-group!
{:web3 web3
:group-id group-id
:identity current-public-key
:keypair keypair
:callback #(dispatch [:incoming-message %1 %2])}))))))))
(fn [{:keys [current-public-key web3 chats]}
[_ {:keys [from]
{:keys [group-id keypair timestamp]} :payload}]]
(let [{:keys [private public]} keypair]
(let [is-active (chats/is-active? group-id)
chat {:chat-id group-id
:public-key public
:private-key private
:updated-at timestamp}]
(when (and (= from (get-in chats [group-id :group-admin]))
(or (not (chats/exists? group-id))
(chats/new-update? timestamp group-id)))
(dispatch [:update-chat! chat])
(when is-active
(protocol/start-watching-group!
{:web3 web3
:group-id group-id
:identity current-public-key
:keypair keypair
:callback #(dispatch [:incoming-message %1 %2])}))))))))
(register-handler :update-message-overhead!
(register-handler
:update-message-overhead!
(u/side-effect!
(fn [_ [_ chat-id network-status]]
(if (= network-status :offline)
(chats/inc-message-overhead chat-id)
(chats/reset-message-overhead chat-id)))))
(fn [_ [_ chat-id network-status]]
(if (= network-status :offline)
(chats/inc-message-overhead chat-id)
(chats/reset-message-overhead chat-id)))))
(reg-fx
::save-public-chat
@ -286,11 +128,11 @@
::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 #(dispatch [:incoming-message %1 %2])})))
{:web3 web3
:group-id group-id
:identity current-public-key
:keypair keypair
:callback #(dispatch [:incoming-message %1 %2])})))
(register-handler-fx
:create-new-public-chat
@ -304,13 +146,13 @@
:is-active true
:timestamp (random/timestamp)}]
(merge
(when-not exists?
{:db (assoc-in db [:chats (:chat-id chat)] chat)
::save-public-chat chat
::start-watching-group (merge {:group-id topic}
(select-keys db [:web3 :current-public-key]))})
{:dispatch-n [[:navigate-to-clean :chat-list]
[:navigate-to :chat topic]]}))))
(when-not exists?
{:db (assoc-in db [:chats (:chat-id chat)] chat)
::save-public-chat chat
::start-watching-group (merge {:group-id topic}
(select-keys db [:web3 :current-public-key]))})
{:dispatch-n [[:navigate-to-clean :chat-list]
[:navigate-to-chat topic]]}))))
(reg-fx
::save-chat
@ -323,23 +165,23 @@
(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)}})
{: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 #(dispatch [:incoming-message %1 %2])}))))
{:web3 web3
:group-id chat-id
:identity current-public-key
:keypair {:public public-key
:private private-key}
:callback #(dispatch [:incoming-message %1 %2])}))))
(defn group-name-from-contacts [contacts selected-contacts username]
(->> (select-keys contacts selected-contacts)
@ -381,7 +223,7 @@
::start-listen-group (merge {:new-chat new-chat}
(select-keys db [:web3 :current-public-key]))
:dispatch-n [[:navigate-to-clean :chat-list]
[:navigate-to :chat (:chat-id new-chat)]]})))
[:navigate-to-chat (:chat-id new-chat)]]})))
(register-handler-fx
:group-chat-invite-received

View File

@ -119,6 +119,7 @@
(update-in [:content :params] #(apply dissoc % hidden-params))
(dissoc :to-message :has-handler :raw-input))
preview (assoc :preview (pr-str preview)))]
(dispatch [:upsert-chat! {:chat-id chat-id}])
(messages/save chat-id command)))))
(register-handler ::dispatch-responded-requests!
@ -201,8 +202,7 @@
(dispatch [::send-message! params])))
(u/side-effect!
(fn [_ [_ {:keys [chat-id message]}]]
(dispatch [:upsert-chat! {:chat-id chat-id
:timestamp (datetime/now-ms)}])
(dispatch [:upsert-chat! {:chat-id chat-id}])
(messages/save chat-id message))))
(register-handler ::send-dapp-message

View File

@ -1,4 +1,5 @@
(ns status-im.chat.models)
(ns status-im.chat.models
(:require [status-im.components.styles :as styles]))
(defn set-chat-ui-props
"Updates ui-props in active chat by merging provided kvs into them"
@ -9,3 +10,37 @@
"Toggles chat ui prop in active chat"
[{:keys [current-chat-id] :as db} ui-element]
(update-in db [:chat-ui-props current-chat-id ui-element] not))
(defn- create-new-chat
[{:keys [db gfy-generator now]} chat-id]
(let [{:keys [name whisper-identity]} (get-in db [:contacts/contacts chat-id])]
{:chat-id chat-id
:name (or name (gfy-generator whisper-identity))
:color styles/default-chat-color
:group-chat false
:is-active true
:timestamp now
:contacts [{:identity chat-id}]}))
(defn add-chat
[{:keys [db] :as cofx} chat-id]
(let [new-chat (create-new-chat cofx chat-id)
existing-chats (:chats db)]
{:db (cond-> (assoc db :new-chat new-chat)
(not (contains? existing-chats chat-id))
(update :chats assoc chat-id new-chat))
:save-chat new-chat}))
(defn update-chat
"Updates chat properties, if chat is not present in db, creates a default new one"
[{:keys [db get-stored-chat]} {:keys [chat-id] :as chat}]
(let [chat (merge (or (get-stored-chat chat-id)
(create-new-chat db chat-id))
chat)]
{:db (update-in db [:chats chat-id] merge chat)
:save-chat chat}))
(defn upsert-chat
"Just like `update-chat` only implicitely updates timestamp"
[cofx chat]
(update-chat cofx (assoc chat :timestamp (:now cofx))))

View File

@ -182,10 +182,9 @@
(reg-handler ::parse-commands! (u/side-effect! parse-commands!))
(reg-handler ::add-commands
[(after (fn [_ [id]]
(dispatch [:invoke-commands-loading-callbacks id])
(dispatch [:invoke-chat-loaded-callbacks id])))
(after #(dispatch [:update-suggestions]))]
(after (fn [_ [id]]
(dispatch [:invoke-commands-loading-callbacks id])
(dispatch [:update-suggestions])))
add-commands)
(reg-handler ::loading-failed! (u/side-effect! loading-failed!))

View File

@ -21,6 +21,7 @@
(defn save
[{:keys [last-message-id chat-id] :as chat}]
;; TODO(janherich): remove `:last-message-id`, seems like it's not used anywhere anymore
(let [chat (assoc chat :last-message-id (or last-message-id ""))]
(data-store/save chat (data-store/exists? chat-id))))

View File

@ -125,7 +125,7 @@
[:initialize-account address]]
(if new-account?
[[:navigate-to-clean :chat-list]
[:navigate-to :chat console-chat-id]]
[:navigate-to-chat console-chat-id]]
[[:navigate-to-clean :chat-list]
[:navigate-to :chat-list]]))}
(log/debug "Error changing acount: " error))))

View File

@ -70,7 +70,7 @@
:on-press #(re-frame/dispatch [:navigate-to :new-chat])}])
(defn chat-list-item [[chat-id chat] edit?]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :chat chat-id])}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to-chat chat-id])}
[react/view
[inner-item/chat-list-item-inner-view (assoc chat :chat-id chat-id) edit?]]])

View File

@ -323,7 +323,7 @@
(when-not (get-in db [:contacts/contacts whisper-identity])
(let [contact (assoc contact :address (public-key->address whisper-identity))]
{:dispatch-n [[::add-new-contact contact]
[:start-chat whisper-identity {} :navigation-replace]]}))))
[:start-chat whisper-identity {:navigation-replace? true}]]}))))
(register-handler-fx
:add-pending-contact
@ -419,10 +419,10 @@
:open-chat-with-contact
(fn [_ [_ {:keys [whisper-identity dapp?] :as contact}]]
{:dispatch-n (concat
[[:navigate-to-clean :chat-list]
[:start-chat whisper-identity {}]]
(when-not dapp?
[[::send-contact-request contact]]))}))
[[:navigate-to-clean :chat-list]
[:start-chat whisper-identity]]
(when-not dapp?
[[::send-contact-request contact]]))}))
(register-handler-fx
:add-contact-handler

View File

@ -1,70 +1,86 @@
(ns status-im.ui.screens.navigation
(:require [re-frame.core :refer [enrich]]
(:require [re-frame.core :as re-frame]
[status-im.utils.handlers :refer [register-handler-db]]
[status-im.constants :refer [console-chat-id]]))
(defmulti preload-data!
(fn [db [_ view-id]] (or view-id (:view-id db))))
;; private helper fns
(defmethod preload-data! :default [db _] db)
(defn -preload-data! [{:keys [was-modal?] :as db} & args]
(if was-modal?
(dissoc db :was-modal?) ;;TODO check how it worked with this bug
(apply preload-data! db args)))
(register-handler-db
:navigate-forget
(enrich preload-data!)
(fn [db [_ new-view-id]]
(assoc db :view-id new-view-id)))
(defn push-view [db view-id]
(defn- push-view [db view-id]
(-> db
(update :navigation-stack conj view-id)
(assoc :view-id view-id)))
(register-handler-db
:navigate-to
(enrich preload-data!)
(fn [{:keys [view-id] :as db} [_ new-view-id]]
(if (= view-id new-view-id)
db
(push-view db new-view-id))))
(register-handler-db
:navigate-to-modal
(enrich preload-data!)
(fn [db [_ modal-view]]
(assoc db :modal modal-view)))
(defn replace-top-element [stack view-id]
(defn- replace-top-element [stack view-id]
(let [stack' (if (> 2 (count stack))
(list :chat-list)
(pop stack))]
(conj stack' view-id)))
(defn replace-view [db view-id]
(defn- replace-view [db view-id]
(-> db
(update :navigation-stack replace-top-element view-id)
(assoc :view-id view-id)))
(register-handler-db
:navigation-replace
(enrich preload-data!)
(fn [db [_ view-id]]
(replace-view db view-id)))
(defn- can-navigate-back? [db]
(not (get db :accounts/creating-account?)))
(defn- navigate-to-clean [db view-id]
(-> db
(assoc :navigation-stack (list))
(push-view view-id)))
;; public fns
(defmulti preload-data!
(fn [db [_ view-id]] (or view-id (:view-id db))))
(defmethod preload-data! :default [db _] db)
(defn- -preload-data! [{:keys [was-modal?] :as db} & args]
(if was-modal?
(dissoc db :was-modal?) ;;TODO check how it worked with this bug
(apply preload-data! db args)))
(defn navigate-to
"Navigates to particular view"
[{:keys [view-id] :as db} go-to-view-id]
(if (= view-id go-to-view-id)
db
(push-view db go-to-view-id)))
;; event handlers
(register-handler-db
:navigate-forget
(re-frame/enrich preload-data!)
(fn [db [_ new-view-id]]
(assoc db :view-id new-view-id)))
(register-handler-db
:navigate-to
(re-frame/enrich preload-data!)
(fn [db [_ new-view-id]]
(navigate-to db new-view-id)))
(register-handler-db
:navigate-to-modal
(re-frame/enrich preload-data!)
(fn [db [_ modal-view]]
(assoc db :modal modal-view)))
(register-handler-db
:navigation-replace
(re-frame/enrich preload-data!)
(fn [db [_ view-id]]
(replace-view db view-id)))
(register-handler-db
:navigate-back
(enrich -preload-data!)
(re-frame/enrich -preload-data!)
(fn [{:keys [navigation-stack view-id modal] :as db} _]
(cond
modal (assoc db :modal nil
:was-modal? true)
:was-modal? true)
(>= 1 (count navigation-stack)) db
:else
@ -78,11 +94,6 @@
(assoc db :view-id first-in-stack)))
db))))
(defn navigate-to-clean [db view-id]
(-> db
(assoc :navigation-stack (list))
(push-view view-id)))
(register-handler-db
:navigate-to-clean
(fn [db [_ view-id]]
@ -90,7 +101,7 @@
(register-handler-db
:navigate-to-tab
(enrich preload-data!)
(re-frame/enrich preload-data!)
(fn [db [_ view-id]]
(-> db
(assoc :prev-tab-view-id (:view-id db))

View File

@ -48,7 +48,7 @@
;; We allow to change phone number only from console because this requires entering SMS verification code.
(fn [{:keys [db]} _]
(let [phone-command (first (get-in db [:contacts/contacts "console" :responses :phone]))]
{:dispatch-n [[:navigate-to :chat console-chat-id]
{:dispatch-n [[:navigate-to-chat console-chat-id]
[:select-chat-input-command phone-command]]})))
(defn get-current-account [{:keys [:accounts/current-account-id] :as db}]

View File

@ -4,22 +4,20 @@
[status-im.ui.screens.wallet.db :as wallet.db]
[re-frame.core :as re-frame]))
(defn chat-loaded-callback [request-command]
(fn []
(re-frame/dispatch [:select-chat-input-command request-command])
;;TODO get rid of timeout
(js/setTimeout #(re-frame/dispatch [:send-current-message]) 100)))
(handlers/register-handler-fx
::wallet-send-chat-request
(fn [_ [_ amount]]
{:dispatch [:select-chat-input-command {:name "request" :prefill [amount]}]
;; TODO get rid of the timeout
:dispatch-later [{:ms 100 :dispatch [:send-current-message]}]}))
(handlers/register-handler-fx
:wallet-send-request
(fn [{{:wallet/keys [request-transaction] :as db} :db} [_ {:keys [whisper-identity]}]]
(let [request-command (first (get-in db [:contacts/contacts "transactor-personal" :commands :request]))]
{:dispatch-n [[:navigate-back]
[:navigate-to-clean :chat-list]
[:add-chat-loaded-callback whisper-identity (chat-loaded-callback
(assoc request-command
:prefill [(:amount request-transaction)]))]
[:start-chat whisper-identity]]})))
(fn [{{:wallet/keys [request-transaction]} :db} [_ {:keys [whisper-identity]}]]
{:dispatch-n [[:navigate-back]
[:navigate-to-clean :chat-list]
[:add-chat-loaded-event whisper-identity [::wallet-send-chat-request (:amount request-transaction)]]
[:start-chat whisper-identity]]}))
(handlers/register-handler-fx
:wallet-validate-request-amount