Refactoring chat events to shorten event chains
This commit is contained in:
parent
5a49926ad0
commit
d9db548e57
|
@ -0,0 +1,98 @@
|
|||
(ns status-im.bots.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn- chats-with-bot [chats bot]
|
||||
(reduce (fn [acc [_ {:keys [chat-id contacts]}]]
|
||||
(let [contacts (map :identity contacts)]
|
||||
(if (some #{bot} contacts)
|
||||
(conj acc chat-id)
|
||||
acc)))
|
||||
[]
|
||||
chats))
|
||||
|
||||
(defn- subscription-values [subscriptions current-bot-db]
|
||||
(reduce (fn [sub-values [sub-name sub-path]]
|
||||
(assoc sub-values sub-name (get-in current-bot-db sub-path)))
|
||||
{}
|
||||
subscriptions))
|
||||
|
||||
;; TODO(janherich): optimze this, for sure we don't need to re-calculate all bot subscriptions every time something in bot db changes
|
||||
(defn- check-subscriptions-fx
|
||||
[db {:keys [bot path value]}]
|
||||
(let [{:keys [bot-db chats]} db
|
||||
subscriptions (get-in db [:bot-subscriptions path])]
|
||||
{:call-jail-function-n
|
||||
(for [{:keys [bot subscriptions name]} subscriptions
|
||||
:let [subs-values (subscription-values subscriptions (get bot-db bot))]]
|
||||
{:chat-id bot
|
||||
:function :subscription
|
||||
:parameters {:name name
|
||||
:subscriptions subs-values}
|
||||
:callback-events-creator (fn [jail-response]
|
||||
(into [[::calculated-subscription
|
||||
{:bot bot
|
||||
:path [name]
|
||||
:result jail-response}]]
|
||||
(map (fn [chat-id]
|
||||
[::calculated-subscription
|
||||
{:bot chat-id
|
||||
:path [name]
|
||||
:result jail-response}])
|
||||
(chats-with-bot chats bot))))})}))
|
||||
|
||||
(defn set-in-bot-db
|
||||
[{:keys [current-chat-id] :as app-db} {:keys [bot path value] :as params}]
|
||||
(let [bot (or bot current-chat-id)
|
||||
new-db (assoc-in app-db (concat [:bot-db bot] path) value)]
|
||||
(merge {:db new-db}
|
||||
(check-subscriptions-fx new-db params))))
|
||||
|
||||
(defn update-bot-db
|
||||
[{:keys [current-chat-id] :as app-db} {:keys [bot db]}]
|
||||
(let [bot (or bot current-chat-id)]
|
||||
(update-in app-db [:bot-db bot] merge db)))
|
||||
|
||||
(defn clear-bot-db
|
||||
[{:keys [current-chat-id] :as app-db}]
|
||||
(assoc-in app-db [:bot-db current-chat-id] nil))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:set-in-bot-db
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [params]]
|
||||
(set-in-bot-db db params)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:update-bot-db
|
||||
[re-frame/trim-v]
|
||||
(fn [db [params]]
|
||||
(update-bot-db db params)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:register-bot-subscription
|
||||
[re-frame/trim-v]
|
||||
(fn [db [{:keys [bot subscriptions] :as opts}]]
|
||||
(reduce
|
||||
(fn [db [sub-name sub-path]]
|
||||
(let [keywordized-sub-path (mapv keyword
|
||||
(if (coll? sub-path)
|
||||
sub-path
|
||||
[sub-path]))]
|
||||
(update-in db [:bot-subscriptions keywordized-sub-path] conj
|
||||
(assoc-in opts [:subscriptions sub-name] keywordized-sub-path))))
|
||||
db
|
||||
subscriptions)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
::calculated-subscription
|
||||
[re-frame/trim-v]
|
||||
(fn [db [{:keys [bot path]
|
||||
{:keys [error result]} :result}]]
|
||||
(if error
|
||||
db
|
||||
(assoc-in db (concat [:bot-db bot] path) (:returned result)))))
|
|
@ -1,77 +0,0 @@
|
|||
(ns status-im.bots.handlers
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.handlers :as u]))
|
||||
|
||||
(defn chats-with-bot [chats bot]
|
||||
(reduce (fn [acc [_ {:keys [chat-id contacts]}]]
|
||||
(let [contacts (map :identity contacts)]
|
||||
(if (some #{bot} contacts)
|
||||
(conj acc chat-id)
|
||||
acc)))
|
||||
[]
|
||||
chats))
|
||||
|
||||
(defn check-subscriptions
|
||||
[{:keys [bot-db chats] :as db} [handler {:keys [path key bot]}]]
|
||||
(let [path' (or path [key])
|
||||
subscriptions (get-in db [:bot-subscriptions path'])
|
||||
current-bot-db (get bot-db bot)]
|
||||
(doseq [{:keys [bot subscriptions name]} subscriptions]
|
||||
(let [subs-values (reduce (fn [res [sub-name sub-path]]
|
||||
(assoc res sub-name (get-in current-bot-db sub-path)))
|
||||
{} subscriptions)]
|
||||
(status/call-function!
|
||||
{:chat-id bot
|
||||
:function :subscription
|
||||
:parameters {:name name
|
||||
:subscriptions subs-values}
|
||||
:callback #(do
|
||||
(re-frame/dispatch
|
||||
[::calculated-subscription {:bot bot
|
||||
:path [name]
|
||||
:result %}])
|
||||
(doseq [chat-id (chats-with-bot chats bot)]
|
||||
(re-frame/dispatch
|
||||
[::calculated-subscription {:bot chat-id
|
||||
:path [name]
|
||||
:result %}])))})))))
|
||||
|
||||
(u/register-handler :set-in-bot-db
|
||||
(re-frame/after check-subscriptions)
|
||||
(fn [{:keys [current-chat-id] :as db} [_ {:keys [bot path value]}]]
|
||||
(let [bot (or bot current-chat-id)]
|
||||
(assoc-in db (concat [:bot-db bot] path) value))))
|
||||
|
||||
(u/register-handler :register-bot-subscription
|
||||
(fn [db [_ {:keys [bot subscriptions] :as opts}]]
|
||||
(reduce
|
||||
(fn [db [sub-name sub-path]]
|
||||
(let [sub-path' (if (coll? sub-path) sub-path [sub-path])
|
||||
sub-path'' (mapv keyword sub-path')]
|
||||
(update-in db [:bot-subscriptions sub-path''] conj
|
||||
(assoc-in opts [:subscriptions sub-name] sub-path''))))
|
||||
db
|
||||
subscriptions)))
|
||||
|
||||
(u/register-handler ::calculated-subscription
|
||||
(u/side-effect!
|
||||
(fn [_ [_ {:keys [bot path]
|
||||
{:keys [error result]} :result
|
||||
:as data}]]
|
||||
(when-not error
|
||||
(let [returned (:returned result)
|
||||
opts {:bot bot
|
||||
:path path
|
||||
:value returned}]
|
||||
(re-frame/dispatch [:set-in-bot-db opts]))))))
|
||||
|
||||
(u/register-handler :update-bot-db
|
||||
(fn [{:keys [current-chat-id] :as app-db} [_ {:keys [bot db]}]]
|
||||
(let [bot (or bot current-chat-id)]
|
||||
(update-in app-db [:bot-db bot] merge db))))
|
||||
|
||||
(u/register-handler :clear-bot-db
|
||||
(fn [{:keys [current-chat-id] :as app-db} [_ {:keys [bot]}]]
|
||||
(let [bot (or bot current-chat-id)]
|
||||
(assoc-in app-db [:bot-db bot] nil))))
|
|
@ -0,0 +1,253 @@
|
|||
(ns status-im.chat.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.chat.models :as model]
|
||||
[status-im.chat.models.unviewed-messages :as unviewed-messages-model]
|
||||
[status-im.chat.sign-up :as sign-up]
|
||||
[status-im.chat.constants :as chat-const]
|
||||
[status-im.data-store.handler-data :as handler-data]
|
||||
[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.protocol.core :as protocol]
|
||||
[status-im.constants :as const]
|
||||
status-im.chat.events.input
|
||||
status-im.chat.events.commands
|
||||
status-im.chat.events.animation
|
||||
status-im.chat.events.receive-message
|
||||
status-im.chat.events.sign-up
|
||||
status-im.chat.events.console))
|
||||
|
||||
;;;; Coeffects
|
||||
|
||||
(re-frame/reg-cofx
|
||||
: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)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
: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)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
: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))))
|
||||
|
||||
;;;; Effects
|
||||
|
||||
(re-frame/reg-fx
|
||||
:update-message
|
||||
(fn [message]
|
||||
(msg-store/update message)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-message
|
||||
(fn [{:keys [chat-id] :as message}]
|
||||
(msg-store/save chat-id message)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-chat
|
||||
(fn [chat]
|
||||
(chats-store/save chat)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-all-contacts
|
||||
(fn [contacts]
|
||||
(contacts-store/save-all contacts)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:protocol-send-seen
|
||||
(fn [params]
|
||||
(protocol/send-seen! params)))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(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)
|
||||
(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
|
||||
:set-layout-height
|
||||
[re-frame/trim-v]
|
||||
(fn [db [height]]
|
||||
(assoc db :layout-height height)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:set-chat-ui-props
|
||||
[re-frame/trim-v]
|
||||
(fn [db [kvs]]
|
||||
(model/set-chat-ui-props db kvs)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:toggle-chat-ui-props
|
||||
[re-frame/trim-v]
|
||||
(fn [db [ui-element]]
|
||||
(model/toggle-chat-ui-prop db ui-element)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:show-message-details
|
||||
[re-frame/trim-v]
|
||||
(fn [db [details]]
|
||||
(model/set-chat-ui-props db {:show-bottom-info? true
|
||||
:show-emoji? false
|
||||
:bottom-info details})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-more-messages
|
||||
[(re-frame/inject-cofx :get-stored-messages)]
|
||||
(fn [{{:keys [current-chat-id loading-allowed] :as db} :db
|
||||
get-stored-messages :get-stored-messages} _]
|
||||
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])]
|
||||
(if (and loading-allowed (not all-loaded?))
|
||||
(let [messages-path [:chats current-chat-id :messages]
|
||||
messages (get-in db messages-path)
|
||||
chat-messages (filter #(= current-chat-id (:chat-id %)) messages)
|
||||
new-messages (get-stored-messages current-chat-id (count chat-messages))
|
||||
all-loaded? (> const/default-number-of-messages (count new-messages))]
|
||||
{:db (-> db
|
||||
(assoc :loading-allowed false)
|
||||
(update-in messages-path concat new-messages)
|
||||
(assoc-in [:chats current-chat-id :all-loaded?] all-loaded?))
|
||||
;; we permit loading more messages again after 400ms
|
||||
:dispatch-later [{:ms 400 :dispatch [:set :loading-allowed true]}]})
|
||||
{:db db}))))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:set-message-shown
|
||||
[re-frame/trim-v]
|
||||
(fn [db [{:keys [chat-id message-id]}]]
|
||||
(update-in db
|
||||
[:chats chat-id :messages]
|
||||
(fn [messages]
|
||||
(map (fn [message]
|
||||
(if (= message-id (:message-id message))
|
||||
(assoc message :new? false)
|
||||
message))
|
||||
messages)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:init-console-chat
|
||||
(fn [{:keys [db]} _]
|
||||
(init-console-chat db false)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:initialize-chats
|
||||
[(re-frame/inject-cofx :all-stored-chats)
|
||||
(re-frame/inject-cofx :stored-unviewed-messages)
|
||||
(re-frame/inject-cofx :get-last-stored-message)
|
||||
(re-frame/inject-cofx :get-message-previews)]
|
||||
(fn [{:keys [db all-stored-chats stored-unviewed-messages get-last-stored-message message-previews]} _]
|
||||
(let [{:accounts/keys [account-creation?]} db
|
||||
new-db (unviewed-messages-model/load-unviewed-messages db stored-unviewed-messages)
|
||||
event [:load-default-contacts!]]
|
||||
(if account-creation?
|
||||
{:db new-db
|
||||
:dispatch-n [event]}
|
||||
(let [chats (->> all-stored-chats
|
||||
(map (fn [{:keys [chat-id] :as chat}]
|
||||
[chat-id (assoc chat :last-message (get-last-stored-message chat-id))]))
|
||||
(into {}))]
|
||||
(-> new-db
|
||||
(assoc-in [:message-data :preview] message-previews)
|
||||
(assoc :handler-data (handler-data/get-all))
|
||||
(assoc :chats chats)
|
||||
(init-console-chat true)
|
||||
(update :dispatch-n conj event)))))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:reload-chats
|
||||
[(re-frame/inject-cofx :all-stored-chats) (re-frame/inject-cofx :get-last-stored-message)]
|
||||
(fn [{:keys [db all-stored-chats get-last-stored-message]} _]
|
||||
(let [updated-chats (->> all-stored-chats
|
||||
(map (fn [{:keys [chat-id] :as chat}]
|
||||
(let [prev-chat (get (:chats db) chat-id)
|
||||
updated-chat (assoc chat :last-message (get-last-stored-message chat-id))]
|
||||
[chat-id (merge prev-chat updated-chat)])))
|
||||
(into {}))]
|
||||
(-> (assoc db :chats updated-chats)
|
||||
(init-console-chat true)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:send-seen!
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [{:keys [message-id chat-id from]}]]
|
||||
(let [{:keys [web3 current-public-key chats]
|
||||
:contacts/keys [contacts]} db
|
||||
{:keys [group-chat public?]} (get chats chat-id)]
|
||||
(cond-> {:db (unviewed-messages-model/remove-unviewed-messages db chat-id)
|
||||
:update-message {:message-id message-id
|
||||
:message-status :seen}}
|
||||
(and (not (get-in contacts [chat-id] :dapp?))
|
||||
(not public?))
|
||||
(assoc :protocol-send-seen
|
||||
{:web3 web3
|
||||
:message (cond-> {:from current-public-key
|
||||
:to from
|
||||
:message-id message-id}
|
||||
group-chat (assoc :group-id chat-id))})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:show-mnemonic
|
||||
[(re-frame/inject-cofx :get-stored-message) re-frame/trim-v]
|
||||
(fn [{:keys [get-stored-message]} [mnemonic signing-phrase]]
|
||||
(let [crazy-math-message? (get-stored-message chat-const/crazy-math-message-id)]
|
||||
{:dispatch-n (sign-up/passphrase-messages-events mnemonic
|
||||
signing-phrase
|
||||
crazy-math-message?)})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:account-generation-message
|
||||
[(re-frame/inject-cofx :get-stored-message)]
|
||||
(fn [{:keys [get-stored-message]} _]
|
||||
(when-not (get-stored-message chat-const/passphrase-message-id)
|
||||
{:dispatch sign-up/account-generation-event})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:move-to-internal-failure-message
|
||||
[(re-frame/inject-cofx :get-stored-message)]
|
||||
(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]}))))
|
|
@ -0,0 +1,75 @@
|
|||
(ns status-im.chat.events.animation
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.views.input.utils :as input-utils]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn set-expandable-height
|
||||
[{:keys [current-chat-id] :as db} key value]
|
||||
(-> db
|
||||
(assoc-in [:chat-animations current-chat-id key :height] value)
|
||||
(update-in [:chat-animations current-chat-id key :changes-counter] inc)))
|
||||
|
||||
(defn choose-predefined-expandable-height
|
||||
[{:keys [current-chat-id chat-ui-props layout-height] :as db} key preset]
|
||||
(if (= preset :max)
|
||||
(set-expandable-height db key :max)
|
||||
(let [input-height (get-in chat-ui-props [current-chat-id :input-height])
|
||||
chat-input-margin (if platform/ios?
|
||||
(get db :keyboard-height)
|
||||
0)
|
||||
bottom (+ input-height chat-input-margin)
|
||||
height (case preset
|
||||
:min input-utils/min-height
|
||||
(input-utils/default-container-area-height bottom layout-height))]
|
||||
(set-expandable-height db key height))))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-db
|
||||
:set-expandable-height
|
||||
[re-frame/trim-v]
|
||||
(fn [db [key value]]
|
||||
(set-expandable-height db key value)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:choose-predefined-expandable-height
|
||||
[re-frame/trim-v]
|
||||
(fn [db [key preset]]
|
||||
(choose-predefined-expandable-height db key preset)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:fix-expandable-height
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [current-chat-id chats chat-ui-props layout-height] :as db} [vy current key]]
|
||||
(let [input-height (get-in chat-ui-props [current-chat-id :input-height])
|
||||
chat-input-margin (if platform/ios?
|
||||
(get db :keyboard-height)
|
||||
0)
|
||||
bottom (+ input-height chat-input-margin)
|
||||
|
||||
min-height input-utils/min-height
|
||||
max-height (input-utils/max-container-area-height bottom layout-height)
|
||||
default-height (input-utils/default-container-area-height bottom layout-height)
|
||||
possible-values [min-height default-height max-height]
|
||||
|
||||
moving-down? (pos? vy)
|
||||
closest-index (->> possible-values
|
||||
(map-indexed vector)
|
||||
(sort-by (fn [[i v]] (Math/abs (- v current))))
|
||||
(ffirst))
|
||||
height (cond (and moving-down? (not= closest-index 0))
|
||||
(get possible-values (dec closest-index))
|
||||
|
||||
(and (not moving-down?) (not= closest-index 2))
|
||||
(get possible-values (inc closest-index))
|
||||
|
||||
moving-down?
|
||||
min-height
|
||||
|
||||
(not moving-down?)
|
||||
max-height)]
|
||||
(set-expandable-height db key height))))
|
|
@ -1,17 +1,15 @@
|
|||
(ns status-im.chat.events.commands
|
||||
(:require [cljs.reader :as reader]
|
||||
[clojure.string :as str]
|
||||
[re-frame.core :refer [reg-fx reg-cofx inject-cofx dispatch trim-v]]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.data-store.messages :as msg-store]
|
||||
[status-im.utils.handlers :refer [register-handler-fx]]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn generate-context
|
||||
(defn- generate-context
|
||||
"Generates context for jail call"
|
||||
[{:keys [chats] :accounts/keys [current-account-id]} chat-id to group-id]
|
||||
(merge {:platform platform/platform
|
||||
|
@ -22,101 +20,80 @@
|
|||
(not (nil? group-id)))}}
|
||||
i18n/delimeters))
|
||||
|
||||
;;;; Coeffects
|
||||
|
||||
(reg-cofx
|
||||
::get-persisted-message
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :get-persisted-message msg-store/get-by-id)))
|
||||
|
||||
;;;; Effects
|
||||
|
||||
(reg-fx
|
||||
::update-persisted-message
|
||||
(fn [message]
|
||||
(msg-store/update message)))
|
||||
|
||||
|
||||
(reg-fx
|
||||
:chat-fx/call-jail
|
||||
(fn [{:keys [callback-events-creator] :as opts}]
|
||||
(status/call-jail
|
||||
(-> opts
|
||||
(dissoc :callback-events-creator)
|
||||
(assoc :callback
|
||||
(fn [jail-response]
|
||||
(doseq [event (callback-events-creator jail-response)]
|
||||
(dispatch event))))))))
|
||||
(defn request-command-message-data
|
||||
"Requests command message data from jail"
|
||||
[db
|
||||
{{:keys [command content-command params type]} :content
|
||||
:keys [chat-id jail-id group-id message-id] :as message}
|
||||
data-type]
|
||||
(let [{:keys [chats]
|
||||
:accounts/keys [current-account-id]
|
||||
:contacts/keys [contacts]} db
|
||||
jail-id (or jail-id chat-id)
|
||||
jail-id (if (get-in chats [jail-id :group-chat])
|
||||
(get-in chats [jail-id :command-suggestions (keyword command) :owner-id])
|
||||
jail-id)]
|
||||
(if (get-in contacts [jail-id :commands-loaded?])
|
||||
(let [path [(if (= :response (keyword type)) :responses :commands)
|
||||
(or content-command command)
|
||||
data-type]
|
||||
to (get-in contacts [chat-id :address])
|
||||
jail-params {:parameters params
|
||||
:context (generate-context db chat-id to group-id)}]
|
||||
{:call-jail {:jail-id jail-id
|
||||
:path path
|
||||
:params jail-params
|
||||
:callback-events-creator (fn [jail-response]
|
||||
[[::jail-command-data-response
|
||||
jail-response message data-type]])}})
|
||||
{:dispatch-n [[:add-commands-loading-callback jail-id
|
||||
#(re-frame/dispatch [:request-command-message-data message data-type])]
|
||||
[:load-commands! jail-id]]})))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
::jail-command-data-response
|
||||
[trim-v]
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [{{:keys [returned]} :result} {:keys [message-id on-requested]} data-type]]
|
||||
(cond-> {}
|
||||
returned
|
||||
(assoc :db (assoc-in db [:message-data data-type message-id] returned))
|
||||
(and returned
|
||||
(= :preview data-type))
|
||||
(assoc ::update-persisted-message {:message-id message-id
|
||||
:preview (prn-str returned)})
|
||||
(assoc :update-message {:message-id message-id
|
||||
:preview (prn-str returned)})
|
||||
on-requested
|
||||
(assoc :dispatch (on-requested returned)))))
|
||||
|
||||
(register-handler-fx
|
||||
:request-command-data
|
||||
[trim-v]
|
||||
(fn [{:keys [db]}
|
||||
[{{:keys [command content-command params type]} :content
|
||||
:keys [chat-id jail-id group-id message-id handler-data] :as message}
|
||||
data-type]]
|
||||
(let [{:keys [chats]
|
||||
:accounts/keys [current-account-id]
|
||||
:contacts/keys [contacts]} db
|
||||
jail-id (or jail-id chat-id)
|
||||
jail-id (if (get-in chats [jail-id :group-chat])
|
||||
(get-in chats [jail-id :command-suggestions (keyword command) :owner-id])
|
||||
jail-id)]
|
||||
(if (get-in contacts [jail-id :commands-loaded?])
|
||||
(let [path [(if (= :response (keyword type)) :responses :commands)
|
||||
(or content-command command)
|
||||
data-type]
|
||||
to (get-in contacts [chat-id :address])
|
||||
jail-params {:parameters params
|
||||
:context (generate-context db chat-id to group-id)}]
|
||||
{:chat-fx/call-jail {:jail-id jail-id
|
||||
:path path
|
||||
:params jail-params
|
||||
:callback-events-creator (fn [jail-response]
|
||||
[[::jail-command-data-response
|
||||
jail-response message data-type]])}})
|
||||
{:dispatch-n [[:add-commands-loading-callback jail-id
|
||||
#(dispatch [:request-command-data message data-type])]
|
||||
[:load-commands! jail-id]]}))))
|
||||
(handlers/register-handler-fx
|
||||
:request-command-message-data
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [message data-type]]
|
||||
(request-command-message-data db message data-type)))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:execute-command-immediately
|
||||
[trim-v]
|
||||
[re-frame/trim-v]
|
||||
(fn [_ [{command-name :name :as command}]]
|
||||
(case (keyword command-name)
|
||||
:grant-permissions
|
||||
{:dispatch [:request-permissions
|
||||
[:read-external-storage]
|
||||
#(dispatch [:initialize-geth])]}
|
||||
#(re-frame/dispatch [:initialize-geth])]}
|
||||
(log/debug "ignoring command: " command))))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:request-command-preview
|
||||
[trim-v (inject-cofx ::get-persisted-message)]
|
||||
(fn [{:keys [db get-persisted-message]} [{:keys [message-id] :as message}]]
|
||||
[re-frame/trim-v (re-frame/inject-cofx :get-stored-message)]
|
||||
(fn [{:keys [db get-stored-message]} [{:keys [message-id] :as message}]]
|
||||
(let [previews (get-in db [:message-data :preview])]
|
||||
(when-not (contains? previews message-id)
|
||||
(let [{serialized-preview :preview} (get-persisted-message message-id)]
|
||||
(let [{serialized-preview :preview} (get-stored-message message-id)]
|
||||
;; if preview is already cached in db, do not request it from jail
|
||||
;; and write it directly to message-data path
|
||||
(if serialized-preview
|
||||
{:db (assoc-in db
|
||||
[:message-data :preview message-id]
|
||||
(reader/read-string serialized-preview))}
|
||||
{:dispatch [:request-command-data message :preview]}))))))
|
||||
(request-command-message-data db message :preview)))))))
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
(ns status-im.chat.events.console
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.constants :as const]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.events.sign-up :as sign-up-events]
|
||||
[status-im.ui.screens.accounts.events :as accounts-events]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.i18n :as i18n]
|
||||
[goog.string :as gstring]
|
||||
goog.string.format))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn console-respond-command-events
|
||||
[command random-id-seq]
|
||||
(let [{:keys [command handler-data]} command]
|
||||
(when command
|
||||
(let [{:keys [name]} command]
|
||||
(case name
|
||||
"js" (let [{:keys [err data messages]} handler-data
|
||||
content (or err data)
|
||||
message-events (mapv (fn [{:keys [message type]} id]
|
||||
[:received-message
|
||||
{:message-id id
|
||||
:content (str type ": " message)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
messages random-id-seq)]
|
||||
(conj message-events
|
||||
[:received-message
|
||||
{:message-id (first random-id-seq)
|
||||
:content (str content)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]))
|
||||
(log/debug "ignoring command: " command))))))
|
||||
|
||||
(def faucet-base-url->url
|
||||
{"http://faucet.ropsten.be:3001" "http://faucet.ropsten.be:3001/donate/0x%s"
|
||||
"http://46.101.129.137:3001" "http://46.101.129.137:3001/donate/0x%s"})
|
||||
|
||||
(defn- faucet-response-event [message-id content]
|
||||
[:received-message
|
||||
{:message-id message-id
|
||||
:content content
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
|
||||
(def console-commands->fx
|
||||
{"password"
|
||||
(fn [{:keys [db]} {:keys [params]}]
|
||||
(accounts-events/create-account db (:password params)))
|
||||
|
||||
"phone"
|
||||
(fn [{:keys [db]} {:keys [params id]}]
|
||||
(-> db
|
||||
(sign-up-events/sign-up (:phone params) id)
|
||||
(as-> fx
|
||||
(assoc fx :dispatch-n [(:dispatch fx)]))
|
||||
(dissoc :dispatch)))
|
||||
|
||||
"confirmation-code"
|
||||
(fn [{:keys [db]} {:keys [params id]}]
|
||||
(sign-up-events/sign-up-confirm db (:code params) id))
|
||||
|
||||
"faucet"
|
||||
(fn [{:keys [db random-id]} {:keys [params id]}]
|
||||
(let [{:accounts/keys [accounts current-account-id]} db
|
||||
current-address (get-in accounts [current-account-id :address])
|
||||
faucet-url (get faucet-base-url->url (:url params))]
|
||||
{:http-get {:url (gstring/format faucet-url current-address)
|
||||
:success-event-creator (fn [_]
|
||||
(faucet-response-event
|
||||
random-id
|
||||
(i18n/label :t/faucet-success)))
|
||||
:failure-event-creator (fn [_]
|
||||
(faucet-response-event
|
||||
random-id
|
||||
(i18n/label :t/faucet-error)))}}))
|
||||
|
||||
"debug"
|
||||
(fn [{:keys [random-id] :as cofx} {:keys [params id]}]
|
||||
(let [debug? (= "On" (:mode params))
|
||||
fx (accounts-events/account-update cofx {:debug? debug?})]
|
||||
(assoc fx :dispatch-n (if debug?
|
||||
[[:debug-server-start]
|
||||
[:received-message
|
||||
{:message-id random-id
|
||||
:content (i18n/label :t/debug-enabled)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]]
|
||||
[[:debug-server-stop]]))))})
|
||||
|
||||
(def commands-names (set (keys console-commands->fx)))
|
||||
|
||||
(def commands-with-delivery-status
|
||||
(disj commands-names "password" "faucet" "debug"))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
;; TODO(janherich) remove this once send-message events are refactored
|
||||
(handlers/register-handler-fx
|
||||
:invoke-console-command-handler!
|
||||
[re-frame/trim-v (re-frame/inject-cofx :random-id) (re-frame/inject-cofx :now)]
|
||||
(fn [cofx [{:keys [chat-id command] :as command-params}]]
|
||||
(let [fx-fn (get console-commands->fx (-> command :command :name))]
|
||||
(-> cofx
|
||||
(fx-fn command)
|
||||
(update :dispatch-n (fnil conj []) [:prepare-command! chat-id command-params])))))
|
||||
|
||||
;; TODO(janherich) remove this once send-message events are refactored
|
||||
(handlers/register-handler-fx
|
||||
:console-respond-command
|
||||
[(re-frame/inject-cofx :random-id-seq) re-frame/trim-v]
|
||||
(fn [{:keys [random-id-seq]} [command]]
|
||||
(when-let [events (console-respond-command-events command random-id-seq)]
|
||||
{:dispatch-n events})))
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,123 @@
|
|||
(ns status-im.chat.events.receive-message
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.clocks :as clocks]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.utils :as chat-utils]
|
||||
[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]))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:pop-up-chat?
|
||||
(fn [cofx]
|
||||
(assoc cofx :pop-up-chat? (fn [chat-id]
|
||||
(or (not (chat-store/exists? chat-id))
|
||||
(chat-store/is-active? chat-id))))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:get-last-clock-value
|
||||
(fn [cofx]
|
||||
(assoc cofx :get-last-clock-value msg-store/get-last-clock-value)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:current-timestamp
|
||||
(fn [cofx]
|
||||
;; TODO (janherich) why is actual timestmap generation in random namespace ?
|
||||
(assoc cofx :current-timestamp (random/timestamp))))
|
||||
|
||||
(defn- get-current-identity
|
||||
[{:accounts/keys [accounts current-account-id]}]
|
||||
(get-in accounts [current-account-id :public-key]))
|
||||
|
||||
(defn- wallet-message
|
||||
[{:keys [content-type] :as message}]
|
||||
(log/debug "Wallet msg")
|
||||
(let [wallet-ct (if (= content-type const/content-type-command)
|
||||
const/content-type-wallet-command
|
||||
const/content-type-wallet-request)]
|
||||
(-> message
|
||||
(assoc :clock-value 0
|
||||
:chat-id const/wallet-chat-id
|
||||
:content-type wallet-ct)
|
||||
(dissoc :group-id))))
|
||||
|
||||
(defn add-message
|
||||
[{:keys [db get-stored-message get-last-stored-message pop-up-chat?
|
||||
get-last-clock-value current-timestamp random-id]}
|
||||
{:keys [from group-id chat-id content-type
|
||||
message-id timestamp clock-value]
|
||||
:as message
|
||||
:or {clock-value 0}}]
|
||||
(let [chat-identifier (or group-id chat-id from)
|
||||
current-identity (get-current-identity db)]
|
||||
;; proceed with adding message if message is not already stored in realm,
|
||||
;; it's not from current user (outgoing message) and it's for relevant chat
|
||||
;; (either current active chat or new chat not existing yet)
|
||||
(if (and (not (get-stored-message chat-identifier))
|
||||
(not= from current-identity)
|
||||
(pop-up-chat? chat-identifier))
|
||||
(let [group-chat? (not (nil? group-id))
|
||||
enriched-message (assoc (chat-utils/check-author-direction
|
||||
(get-last-stored-message chat-identifier)
|
||||
message)
|
||||
:chat-id chat-identifier
|
||||
:timestamp (or timestamp current-timestamp)
|
||||
: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-in enriched-message [:content :command])
|
||||
(update :dispatch-n conj [:request-command-preview enriched-message])
|
||||
|
||||
(= (:content-type enriched-message) const/content-type-command-request)
|
||||
(update :dispatch-n conj [:add-request chat-identifier enriched-message])
|
||||
;; TODO(janherich) refactor this ugly special treatment of wallet send commands for logged in user
|
||||
(and (= (get-in message [:content :params :bot-db :public :recipient :whisper-identity])
|
||||
current-identity)
|
||||
(= content-type const/content-type-command)
|
||||
(not= chat-identifier const/wallet-chat-id)
|
||||
(= "send" (get-in message [:content :command])))
|
||||
(update :dispatch-n conj [:received-message (wallet-message (assoc message :message-id random-id))])))
|
||||
{:db db})))
|
||||
|
||||
(def ^:private receive-interceptors
|
||||
[(re-frame/inject-cofx :get-stored-message) (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 :current-timestamp) (re-frame/inject-cofx :random-id)
|
||||
re-frame/trim-v])
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:received-protocol-message!
|
||||
receive-interceptors
|
||||
(fn [cofx [{:keys [from to payload]}]]
|
||||
(add-message cofx (merge payload
|
||||
{:from from
|
||||
:to to
|
||||
:chat-id from}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:received-message
|
||||
receive-interceptors
|
||||
(fn [cofx [message]]
|
||||
(add-message cofx message)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:received-message-when-commands-loaded
|
||||
receive-interceptors
|
||||
(fn [{:keys [db] :as cofx} [chat-id message]]
|
||||
(if (and (:status-node-started? db)
|
||||
(get-in db [:contacts/contacts chat-id :commands-loaded?]))
|
||||
(add-message cofx message)
|
||||
{:dispatch-later [{:ms 400 :dispatch [:received-message-when-commands-loaded chat-id message]}]})))
|
|
@ -0,0 +1,123 @@
|
|||
(ns status-im.chat.events.sign-up
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.phone-number :as phone-number-util]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.sign-up :as sign-up]
|
||||
[status-im.ui.screens.accounts.events :as accounts-events]
|
||||
[status-im.ui.screens.contacts.events :as contacts-events]))
|
||||
|
||||
;;;; Helpers fns
|
||||
|
||||
(defn sign-up
|
||||
"Creates effects for signing up"
|
||||
[db phone-number message-id]
|
||||
(let [current-account-id (:accounts/current-account-id db)
|
||||
{:keys [public-key address]} (get-in db [:accounts/accounts current-account-id])]
|
||||
{:dispatch sign-up/start-listening-confirmation-code-sms-event
|
||||
:http-post {:action "sign-up"
|
||||
:data {:phone-number (phone-number-util/format-phone-number phone-number)
|
||||
:whisper-identity public-key
|
||||
:address address}
|
||||
:success-event-creator (fn [_]
|
||||
[::sign-up-success message-id])
|
||||
:failure-event-creator (fn [_]
|
||||
[::http-request-failure [::sign-up phone-number message-id]])}}))
|
||||
|
||||
(defn sign-up-confirm
|
||||
"Creates effects for sign-up confirmation"
|
||||
[db confirmation-code message-id]
|
||||
{:http-post {:action "sign-up-confirm"
|
||||
:data {:code confirmation-code}
|
||||
:success-event-creator (fn [body]
|
||||
[::sign-up-confirm-response body message-id])
|
||||
:failure-event-creator (fn [_]
|
||||
[::http-request-failure [::sign-up-confirm confirmation-code message-id]])}})
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::sign-up
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [phone-number message-id]]
|
||||
(sign-up db phone-number message-id)))
|
||||
|
||||
(defn- message-seen [{:keys [db] :as fx} message-id]
|
||||
(merge fx
|
||||
{:db (assoc-in db [:message-data :statuses message-id] {:status :seen})
|
||||
:update-message {:message-id message-id
|
||||
:message-status :seen}}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::sign-up-success
|
||||
[re-frame/trim-v (re-frame/inject-cofx :random-id)]
|
||||
(fn [{:keys [db random-id]} message-id]
|
||||
(-> {:db db
|
||||
:dispatch-n [;; create manual way for entering confirmation code
|
||||
(sign-up/enter-confirmation-code-event random-id)
|
||||
;; create automatic way for receiving confirmation code
|
||||
sign-up/start-listening-confirmation-code-sms-event]}
|
||||
(message-seen message-id))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:start-listening-confirmation-code-sms
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [sms-listener]]
|
||||
{:db (if-not (:confirmation-code-sms-listener db)
|
||||
(assoc db :confirmation-code-sms-listener sms-listener)
|
||||
db)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::sign-up-confirm
|
||||
(fn [{:keys [db]} [confirmation-code message-id]]
|
||||
(sign-up-confirm db confirmation-code message-id)))
|
||||
|
||||
(defn- sign-up-confirmed [{:keys [db] :as fx}]
|
||||
(cond-> (update fx :dispatch-n conj [:request-permissions
|
||||
[:read-contacts]
|
||||
#(re-frame/dispatch [:sync-contacts (fn [contacts]
|
||||
[::contacts-synced contacts])])])
|
||||
(:confirmation-code-sms-listener db)
|
||||
(merge {:db (dissoc db :confirmation-code-sms-listener)
|
||||
:remove-sms-listener (:confirmation-code-sms-listener db)})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::sign-up-confirm-response
|
||||
[re-frame/trim-v (re-frame/inject-cofx :random-id)]
|
||||
(fn [{:keys [db random-id]} [{:keys [message status]} message-id]]
|
||||
(cond-> {:db db
|
||||
:dispatch-n [[:received-message
|
||||
{:message-id random-id
|
||||
:content message
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]]}
|
||||
message-id
|
||||
(message-seen message-id)
|
||||
|
||||
(= "confirmed" status)
|
||||
sign-up-confirmed
|
||||
|
||||
(= "failed" status)
|
||||
(update :dispatch-n conj (sign-up/incorrect-confirmation-code-event random-id)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::contacts-synced
|
||||
[re-frame/trim-v (re-frame/inject-cofx :random-id) (re-frame/inject-cofx :now)]
|
||||
(fn [{:keys [db random-id] :as cofx} [contacts]]
|
||||
(-> db
|
||||
(contacts-events/add-contacts contacts)
|
||||
(as-> fx
|
||||
(merge fx
|
||||
(accounts-events/account-update (assoc cofx :db (:db fx)) {:signed-up? true})
|
||||
{:dispatch (sign-up/contacts-synchronised-event random-id)})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::http-request-failure
|
||||
[re-frame/trim-v]
|
||||
(fn [_ [original-event-vector]]
|
||||
;; TODO(janherich): in case of http request failure, we will try to hit http endpoint in loop forever,
|
||||
;; maybe it's better to cut it after N tries and display error message with explanation to user
|
||||
{:dispatch-later [{:ms 1000 :dispatch original-event-vector}]}))
|
|
@ -9,180 +9,30 @@
|
|||
[status-im.protocol.core :as protocol]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.data-store.handler-data :as handler-data]
|
||||
[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
|
||||
default-number-of-messages
|
||||
content-type-command-request
|
||||
console-chat-id
|
||||
wallet-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.handlers.server :as server]
|
||||
[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.chat.events.input
|
||||
status-im.chat.events.commands
|
||||
status-im.chat.handlers.animation
|
||||
status-im.chat.handlers.requests
|
||||
status-im.chat.handlers.unviewed-messages
|
||||
status-im.chat.handlers.send-message
|
||||
status-im.chat.handlers.receive-message
|
||||
status-im.chat.handlers.faucet
|
||||
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
|
||||
status-im.chat.handlers.console
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(register-handler :set-layout-height
|
||||
(fn [db [_ height]]
|
||||
(assoc db :layout-height height)))
|
||||
|
||||
(register-handler :set-chat-ui-props
|
||||
(fn [{:keys [current-chat-id] :as db} [_ kvs]]
|
||||
(update-in db [:chat-ui-props current-chat-id] merge kvs)))
|
||||
|
||||
(register-handler :toggle-chat-ui-props
|
||||
(fn [{:keys [current-chat-id chat-ui-props] :as db} [_ ui-element chat-id]]
|
||||
(let [chat-id (or chat-id current-chat-id)]
|
||||
(update-in db [:chat-ui-props chat-id ui-element] not))))
|
||||
|
||||
(register-handler :show-message-details
|
||||
(u/side-effect!
|
||||
(fn [_ [_ details]]
|
||||
(dispatch [:set-chat-ui-props {:show-bottom-info? true
|
||||
:show-emoji? false
|
||||
:bottom-info details}]))))
|
||||
|
||||
(register-handler :load-more-messages
|
||||
(fn [{:keys [current-chat-id loading-allowed] :as db} _]
|
||||
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])]
|
||||
(if loading-allowed
|
||||
(do (am/go
|
||||
(<! (a/timeout 400))
|
||||
(dispatch [:set :loading-allowed true]))
|
||||
(if all-loaded?
|
||||
db
|
||||
(let [messages-path [:chats current-chat-id :messages]
|
||||
messages (get-in db messages-path)
|
||||
chat-messages (filter #(= current-chat-id (:chat-id %)) messages)
|
||||
new-messages (messages/get-by-chat-id current-chat-id (count chat-messages))
|
||||
all-loaded? (> default-number-of-messages (count new-messages))]
|
||||
(-> db
|
||||
(assoc :loading-allowed false)
|
||||
(update-in messages-path concat new-messages)
|
||||
(assoc-in [:chats current-chat-id :all-loaded?] all-loaded?)))))
|
||||
db))))
|
||||
|
||||
(defn set-message-shown
|
||||
[db chat-id message-id]
|
||||
(update-in db
|
||||
[:chats chat-id :messages]
|
||||
(fn [messages]
|
||||
(map (fn [message]
|
||||
(if (= message-id (:message-id message))
|
||||
(assoc message :new? false)
|
||||
message))
|
||||
messages))))
|
||||
|
||||
(register-handler :set-message-shown
|
||||
(fn [db [_ {:keys [chat-id message-id]}]]
|
||||
(set-message-shown db chat-id message-id)))
|
||||
|
||||
(register-handler :cancel-command
|
||||
(fn [{:keys [current-chat-id] :as db} _]
|
||||
(-> db
|
||||
(assoc-in [:chats current-chat-id :command-input] {})
|
||||
(update-in [:chats current-chat-id :input-text] safe-trim))))
|
||||
|
||||
(defn init-console-chat
|
||||
([{:keys [chats] :accounts/keys [current-account-id] :as db} existing-account?]
|
||||
(let [new-chat sign-up-service/console-chat]
|
||||
(if (chats console-chat-id)
|
||||
db
|
||||
(do
|
||||
(dispatch [:add-contacts [sign-up-service/console-contact]])
|
||||
(chats/save new-chat)
|
||||
(contacts/save-all [sign-up-service/console-contact])
|
||||
(when-not current-account-id
|
||||
(sign-up-service/intro))
|
||||
(when existing-account?
|
||||
(sign-up-service/start-signup))
|
||||
(-> db
|
||||
(assoc :new-chat new-chat)
|
||||
(update :chats assoc console-chat-id new-chat)
|
||||
(assoc :current-chat-id console-chat-id)))))))
|
||||
|
||||
(register-handler :init-console-chat
|
||||
(fn [db _]
|
||||
(init-console-chat db false)))
|
||||
|
||||
(register-handler :account-generation-message
|
||||
(u/side-effect!
|
||||
(fn [_]
|
||||
(when-not (messages/get-by-id chat-consts/passphrase-message-id)
|
||||
(sign-up-service/account-generation-message)))))
|
||||
|
||||
(register-handler :move-to-internal-failure-message
|
||||
(u/side-effect!
|
||||
(fn [_]
|
||||
(when-not (messages/get-by-id chat-consts/move-to-internal-failure-message-id)
|
||||
(sign-up-service/move-to-internal-failure-message)))))
|
||||
|
||||
(register-handler :show-mnemonic
|
||||
(u/side-effect!
|
||||
(fn [_ [_ mnemonic signing-phrase]]
|
||||
(let [crazy-math-message? (messages/get-by-id chat-consts/crazy-math-message-id)]
|
||||
(sign-up-service/passphrase-messages mnemonic signing-phrase crazy-math-message?)))))
|
||||
|
||||
(defn- handle-sms [{body :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" body)]
|
||||
(dispatch [:sign-up-confirm (second matches)])))
|
||||
|
||||
(register-handler :sign-up
|
||||
(after (fn [_ [_ phone-number]]
|
||||
(dispatch [:account-update {:phone phone-number}])))
|
||||
(fn [db [_ phone-number message-id]]
|
||||
(sign-up-service/start-listening-confirmation-code-sms)
|
||||
(let [formatted (format-phone-number phone-number)]
|
||||
(server/sign-up db
|
||||
formatted
|
||||
message-id
|
||||
sign-up-service/on-sign-up-response))))
|
||||
|
||||
(register-handler :start-listening-confirmation-code-sms
|
||||
(fn [db [_ listener]]
|
||||
(if-not (:confirmation-code-sms-listener db)
|
||||
(assoc db :confirmation-code-sms-listener listener)
|
||||
db)))
|
||||
|
||||
(register-handler :stop-listening-confirmation-code-sms
|
||||
(fn [db]
|
||||
(if (:confirmation-code-sms-listener db)
|
||||
(sign-up-service/stop-listening-confirmation-code-sms db)
|
||||
db)))
|
||||
|
||||
(register-handler :sign-up-confirm
|
||||
(u/side-effect!
|
||||
(fn [_ [_ confirmation-code message-id]]
|
||||
(server/sign-up-confirm
|
||||
confirmation-code
|
||||
message-id
|
||||
sign-up-service/on-send-code-response))))
|
||||
|
||||
(register-handler :set-signed-up
|
||||
(u/side-effect!
|
||||
(fn [_ [_ signed-up]]
|
||||
(dispatch [:account-update {:signed-up? signed-up}]))))
|
||||
|
||||
(defn load-messages!
|
||||
([db] (load-messages! db nil))
|
||||
([{:keys [current-chat-id] :as db} _]
|
||||
|
@ -208,47 +58,6 @@
|
|||
init-chat
|
||||
load-commands!))
|
||||
|
||||
(defn initialize-chats
|
||||
[{:keys [loaded-chats chats] :accounts/keys [account-creation?] :as db} _]
|
||||
(let [chats' (if account-creation?
|
||||
chats
|
||||
(->> loaded-chats
|
||||
(map (fn [{:keys [chat-id] :as chat}]
|
||||
(let [last-message (messages/get-last-message chat-id)]
|
||||
[chat-id (assoc chat :last-message last-message)])))
|
||||
(into {})))]
|
||||
|
||||
(-> db
|
||||
(assoc :chats chats')
|
||||
(assoc :handler-data (handler-data/get-all))
|
||||
(dissoc :loaded-chats)
|
||||
(init-console-chat true))))
|
||||
|
||||
(defn load-chats!
|
||||
[{:accounts/keys [account-creation?] :as db} _]
|
||||
(if account-creation?
|
||||
db
|
||||
(assoc db :loaded-chats (chats/get-all))))
|
||||
|
||||
(register-handler :initialize-chats
|
||||
[(after #(dispatch [:load-unviewed-messages!]))
|
||||
(after #(dispatch [:load-default-contacts!]))]
|
||||
(u/handlers->
|
||||
load-chats!
|
||||
initialize-chats))
|
||||
|
||||
(register-handler :reload-chats
|
||||
(fn [{:keys [chats] :as db} _]
|
||||
(let [chats' (->> (chats/get-all)
|
||||
(map (fn [{:keys [chat-id] :as chat}]
|
||||
(let [last-message (messages/get-last-message chat-id)
|
||||
prev-chat (get chats chat-id)
|
||||
new-chat (assoc chat :last-message last-message)]
|
||||
[chat-id (merge prev-chat new-chat)])))
|
||||
(into {}))]
|
||||
(-> (assoc db :chats chats')
|
||||
(init-console-chat true)))))
|
||||
|
||||
(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)
|
||||
|
@ -427,27 +236,6 @@
|
|||
remove-pending-messages!
|
||||
delete-chat!))
|
||||
|
||||
(defn send-seen!
|
||||
[{:keys [web3 current-public-key chats]
|
||||
:contacts/keys [contacts]}
|
||||
[_ {:keys [from chat-id message-id]}]]
|
||||
(when-not (get-in contacts [chat-id :dapp?])
|
||||
(let [{:keys [group-chat public?]} (chats chat-id)]
|
||||
(when-not public?
|
||||
(protocol/send-seen! {:web3 web3
|
||||
:message {:from current-public-key
|
||||
:to from
|
||||
:group-id (when group-chat chat-id)
|
||||
:message-id message-id}})))))
|
||||
|
||||
(register-handler :send-seen!
|
||||
[(after (fn [_ [_ {:keys [message-id]}]]
|
||||
(messages/update {:message-id message-id
|
||||
:message-status :seen})))
|
||||
(after (fn [_ [_ {:keys [chat-id]}]]
|
||||
(dispatch [:remove-unviewed-messages chat-id])))]
|
||||
(u/side-effect! send-seen!))
|
||||
|
||||
(register-handler :check-and-open-dapp!
|
||||
(u/side-effect!
|
||||
(fn [{:keys [current-chat-id global-commands]
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
(ns status-im.chat.handlers.animation
|
||||
(:require [re-frame.core :refer [after dispatch subscribe debug path]]
|
||||
[status-im.chat.views.input.utils :as input-utils]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(handlers/register-handler :set-expandable-height
|
||||
(fn [{:keys [current-chat-id] :as db} [_ key value]]
|
||||
(-> db
|
||||
(assoc-in [:chat-animations current-chat-id key :height] value)
|
||||
(update-in [:chat-animations current-chat-id key :changes-counter] inc))))
|
||||
|
||||
(handlers/register-handler :hide-expandable
|
||||
(handlers/side-effect!
|
||||
(fn [_ [_ key]]
|
||||
(dispatch [:set-expandable-height key 1]))))
|
||||
|
||||
(handlers/register-handler :choose-predefined-expandable-height
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id chat-ui-props layout-height] :as db} [_ key preset]]
|
||||
(if (= preset :max)
|
||||
(dispatch [:set-expandable-height key :max])
|
||||
(let [input-height (get-in chat-ui-props [current-chat-id :input-height])
|
||||
chat-input-margin (if platform/ios?
|
||||
(get db :keyboard-height)
|
||||
0)
|
||||
bottom (+ input-height chat-input-margin)
|
||||
height (case preset
|
||||
:min input-utils/min-height
|
||||
(input-utils/default-container-area-height bottom layout-height))]
|
||||
(dispatch [:set-expandable-height key height]))))))
|
||||
|
||||
(handlers/register-handler :fix-expandable-height
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-chat-id chats chat-ui-props layout-height] :as db} [_ vy current key]]
|
||||
(let [input-height (get-in chat-ui-props [current-chat-id :input-height])
|
||||
chat-input-margin (if platform/ios?
|
||||
(get db :keyboard-height)
|
||||
0)
|
||||
bottom (+ input-height chat-input-margin)
|
||||
|
||||
min-height input-utils/min-height
|
||||
max-height (input-utils/max-container-area-height bottom layout-height)
|
||||
default-height (input-utils/default-container-area-height bottom layout-height)
|
||||
possible-values [min-height default-height max-height]
|
||||
|
||||
moving-down? (pos? vy)
|
||||
closest-index (->> possible-values
|
||||
(map-indexed vector)
|
||||
(sort-by (fn [[i v]] (Math/abs (- v current))))
|
||||
(ffirst))
|
||||
height (cond (and moving-down? (not= closest-index 0))
|
||||
(get possible-values (dec closest-index))
|
||||
|
||||
(and (not moving-down?) (not= closest-index 2))
|
||||
(get possible-values (inc closest-index))
|
||||
|
||||
moving-down?
|
||||
min-height
|
||||
|
||||
(not moving-down?)
|
||||
max-height)]
|
||||
(dispatch [:set-expandable-height key height])))))
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
(ns status-im.chat.handlers.console
|
||||
(:require [re-frame.core :refer [dispatch dispatch-sync after]]
|
||||
[status-im.utils.handlers :refer [register-handler] :as u]
|
||||
[status-im.constants :refer [console-chat-id
|
||||
text-content-type]]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.utils.random :as random]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def console-commands
|
||||
{:password
|
||||
(fn [{:keys [password]} _]
|
||||
(dispatch [:create-account password]))
|
||||
|
||||
:phone
|
||||
(fn [{:keys [phone]} id]
|
||||
(dispatch [:sign-up phone id]))
|
||||
|
||||
:confirmation-code
|
||||
(fn [{:keys [code]} id]
|
||||
(dispatch [:sign-up-confirm code id]))
|
||||
|
||||
:faucet
|
||||
(fn [{:keys [url]} id]
|
||||
(dispatch [:open-faucet url id]))
|
||||
|
||||
:debug
|
||||
(fn [{:keys [mode]} id]
|
||||
(let [debug-on? (= mode "On")]
|
||||
(dispatch [:account-update {:debug? debug-on?}])
|
||||
(if debug-on?
|
||||
(do
|
||||
(dispatch [:debug-server-start])
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (label :t/debug-enabled)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(dispatch [:debug-server-stop]))))})
|
||||
|
||||
(def commands-names (set (keys console-commands)))
|
||||
|
||||
(def commands-with-delivery-status
|
||||
(disj commands-names :password :faucet :debug))
|
||||
|
||||
(register-handler :invoke-console-command-handler!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ {{:keys [command
|
||||
params
|
||||
id]
|
||||
:as content} :command
|
||||
chat-id :chat-id
|
||||
:as all-params}]]
|
||||
(let [{:keys [name]} command]
|
||||
(dispatch [:prepare-command! chat-id all-params])
|
||||
((console-commands (keyword name)) params id)))))
|
||||
|
||||
(register-handler :set-message-status
|
||||
(after
|
||||
(fn [_ [_ message-id status]]
|
||||
(messages/update {:message-id message-id
|
||||
:message-status status})))
|
||||
(fn [db [_ message-id status]]
|
||||
(assoc-in db [:message-data :statuses message-id] {:status status})))
|
||||
|
||||
(register-handler :console-respond-command
|
||||
(u/side-effect!
|
||||
(fn [_ [_ {:keys [command]}]]
|
||||
(let [{:keys [command handler-data]} command]
|
||||
(when command
|
||||
(let [{:keys [name]} command]
|
||||
(case name
|
||||
"js" (let [{:keys [err data messages]} handler-data
|
||||
content (or err data)]
|
||||
(doseq [message messages]
|
||||
(let [{:keys [message type]} message]
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (str type ": " message)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])))
|
||||
(when content
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (str content)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])))
|
||||
(log/debug "ignoring command: " command))))))))
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
(ns status-im.chat.handlers.faucet
|
||||
(:require [re-frame.core :refer [dispatch]]
|
||||
[status-im.utils.handlers :refer [register-handler] :as u]
|
||||
[status-im.utils.utils :refer [http-get]]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.constants :refer [console-chat-id
|
||||
text-content-type]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[goog.string :as gstring]
|
||||
goog.string.format))
|
||||
|
||||
(def faucets
|
||||
[{:name "http://faucet.ropsten.be:3001"
|
||||
:type :api
|
||||
:api-url "http://faucet.ropsten.be:3001/donate/0x%s"}
|
||||
{:name "http://46.101.129.137:3001"
|
||||
:type :api
|
||||
:api-url "http://46.101.129.137:3001/donate/0x%s"}])
|
||||
|
||||
(defn faucet-by-name [faucet-name]
|
||||
(->> faucets
|
||||
(filter #(= (:name %) faucet-name))
|
||||
(first)))
|
||||
|
||||
(defn received-message [content]
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content content
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
|
||||
(defmulti open-faucet (fn [_ _ {:keys [type]}] type))
|
||||
|
||||
(defmethod open-faucet :api
|
||||
[_ current-address {:keys [api-url]}]
|
||||
(let [api-url (gstring/format api-url current-address)]
|
||||
(http-get api-url
|
||||
#(received-message (label :t/faucet-success))
|
||||
#(received-message (label :t/faucet-error)))))
|
||||
|
||||
(register-handler :open-faucet
|
||||
(u/side-effect!
|
||||
(fn [{:accounts/keys [accounts current-account-id]} [_ faucet-name _]]
|
||||
(if-let [faucet (faucet-by-name faucet-name)]
|
||||
(let [current-address (get-in accounts [current-account-id :address])]
|
||||
(open-faucet faucet-name current-address faucet))))))
|
|
@ -1,112 +0,0 @@
|
|||
(ns status-im.chat.handlers.receive-message
|
||||
(:require [status-im.utils.handlers :refer [register-handler] :as u]
|
||||
[re-frame.core :refer [enrich after debug dispatch path]]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.chat.utils :as cu]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.constants :refer [wallet-chat-id
|
||||
content-type-command
|
||||
content-type-command-request]
|
||||
:as c]
|
||||
[cljs.reader :refer [read-string]]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.utils.scheduler :as s]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.clocks :as clocks]))
|
||||
|
||||
(defn store-message [{chat-id :chat-id :as message}]
|
||||
(messages/save chat-id (dissoc message :new?)))
|
||||
|
||||
(defn get-current-identity
|
||||
[{:accounts/keys [accounts current-account-id]}]
|
||||
(get-in accounts [current-account-id :public-key]))
|
||||
|
||||
(declare add-message-to-wallet)
|
||||
|
||||
(defn add-message
|
||||
[db {:keys [from group-id chat-id
|
||||
message-id timestamp clock-value]
|
||||
:as message
|
||||
:or {clock-value 0}}]
|
||||
(let [same-message (messages/get-by-id message-id)
|
||||
current-identity (get-current-identity db)
|
||||
chat-id' (or group-id chat-id from)
|
||||
exists? (chats/exists? chat-id')
|
||||
active? (chats/is-active? chat-id')
|
||||
local-clock (messages/get-last-clock-value chat-id')
|
||||
clock-new (clocks/receive clock-value local-clock)
|
||||
recipient-pub-key (get-in message [:content :params :bot-db :public :recipient :whisper-identity])]
|
||||
(when (and (not same-message)
|
||||
(not= from current-identity)
|
||||
(or (not exists?) active?))
|
||||
(let [group-chat? (not (nil? group-id))
|
||||
previous-message (messages/get-last-message chat-id')
|
||||
message' (assoc (cu/check-author-direction previous-message message)
|
||||
:chat-id chat-id'
|
||||
:timestamp (or timestamp (random/timestamp))
|
||||
:clock-value clock-new)]
|
||||
(store-message message')
|
||||
(dispatch [:upsert-chat! {:chat-id chat-id'
|
||||
:group-chat group-chat?}])
|
||||
(when (get-in message [:content :command])
|
||||
(dispatch [:request-command-preview message]))
|
||||
(dispatch [::add-message chat-id' message'])
|
||||
(dispatch [::set-last-message message'])
|
||||
(when (= (:content-type message') content-type-command-request)
|
||||
(dispatch [:add-request chat-id' message']))
|
||||
(dispatch [:add-unviewed-message chat-id' message-id]))
|
||||
(if (and
|
||||
(= recipient-pub-key current-identity)
|
||||
(= (:content-type message) content-type-command)
|
||||
(not= chat-id' wallet-chat-id)
|
||||
(= "send" (get-in message [:content :command])))
|
||||
(add-message-to-wallet db message)))))
|
||||
|
||||
(defn add-message-to-wallet [db {:keys [content-type] :as message}]
|
||||
(let [ct (if (= content-type c/content-type-command)
|
||||
c/content-type-wallet-command
|
||||
c/content-type-wallet-request)
|
||||
message' (-> (assoc message :clock-value 0
|
||||
:message-id (random/id)
|
||||
:chat-id wallet-chat-id
|
||||
:content-type ct)
|
||||
(dissoc :group-id))]
|
||||
(add-message db message')))
|
||||
|
||||
(register-handler :received-protocol-message!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ {:keys [from to payload]}]]
|
||||
(dispatch [:received-message (merge payload
|
||||
{:from from
|
||||
:to to
|
||||
:chat-id from})]))))
|
||||
|
||||
(register-handler :received-message
|
||||
(after #(dispatch [:update-suggestions]))
|
||||
(u/side-effect!
|
||||
(fn [db [_ message]]
|
||||
(add-message db message))))
|
||||
|
||||
(register-handler ::add-message
|
||||
(fn [db [_ add-to-chat-id {:keys [chat-id new?] :as message}]]
|
||||
(cu/add-message-to-db db add-to-chat-id chat-id message new?)))
|
||||
|
||||
(register-handler ::set-last-message
|
||||
(fn [{:keys [chats] :as db} [_ {:keys [chat-id] :as message}]]
|
||||
(dispatch [:request-command-data message :short-preview])
|
||||
(assoc-in db [:chats chat-id :last-message] message)))
|
||||
|
||||
(defn commands-loaded? [db chat-id]
|
||||
(get-in db [:contacts/contacts chat-id :commands-loaded?]))
|
||||
|
||||
(def timeout 400)
|
||||
|
||||
(register-handler :received-message-when-commands-loaded
|
||||
(u/side-effect!
|
||||
(fn [{:keys [status-node-started?] :as db} [_ chat-id message]]
|
||||
(if (and status-node-started? (commands-loaded? db chat-id))
|
||||
(dispatch [:received-message message])
|
||||
(s/execute-later
|
||||
#(dispatch [:received-message-when-commands-loaded chat-id message])
|
||||
timeout)))))
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[taoensso.timbre :refer-macros [debug] :as log]
|
||||
[status-im.chat.handlers.console :as console]
|
||||
[status-im.chat.events.console :as console]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.clocks :as clocks]))
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
(defn console-command? [chat-id command-name]
|
||||
(and (= console-chat-id chat-id)
|
||||
(console/commands-names (keyword command-name))))
|
||||
(console/commands-names command-name)))
|
||||
|
||||
(register-handler :check-commands-handlers!
|
||||
(u/side-effect!
|
||||
|
@ -124,10 +124,12 @@
|
|||
|
||||
(register-handler ::save-command!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ chat-id {:keys [command]} hidden-params]]
|
||||
(let [command (-> command
|
||||
(update-in [:content :params] #(apply dissoc % hidden-params))
|
||||
(dissoc :to-message :has-handler))]
|
||||
(fn [db [_ chat-id {:keys [command]} hidden-params]]
|
||||
(let [preview (get-in db [:message-data :preview (:message-id command)])
|
||||
command (cond-> (-> command
|
||||
(update-in [:content :params] #(apply dissoc % hidden-params))
|
||||
(dissoc :to-message :has-handler :raw-input))
|
||||
preview (assoc :preview (pr-str preview)))]
|
||||
(messages/save chat-id command)))))
|
||||
|
||||
(register-handler ::dispatch-responded-requests!
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
(ns status-im.chat.handlers.unviewed-messages
|
||||
(:require [re-frame.core :refer [after enrich path dispatch]]
|
||||
[status-im.utils.handlers :refer [register-handler]]
|
||||
[status-im.data-store.messages :as messages]))
|
||||
|
||||
(defn set-unviewed-messages [db]
|
||||
(let [messages (->> (:raw-unviewed-messages db)
|
||||
(group-by :chat-id)
|
||||
(map (fn [[id messages]]
|
||||
[id {:messages-ids (map :message-id messages)
|
||||
:count (count messages)}]))
|
||||
(into {}))]
|
||||
(-> db
|
||||
(assoc :unviewed-messages messages)
|
||||
(dissoc :raw-unviewed-messages))))
|
||||
|
||||
(defn load-messages! [db]
|
||||
(let [messages (messages/get-unviewed)]
|
||||
(assoc db :raw-unviewed-messages messages)))
|
||||
|
||||
(register-handler ::set-unviewed-messages set-unviewed-messages)
|
||||
|
||||
(register-handler :load-unviewed-messages!
|
||||
(after #(dispatch [::set-unviewed-messages]))
|
||||
load-messages!)
|
||||
|
||||
(register-handler :add-unviewed-message
|
||||
(path :unviewed-messages)
|
||||
(fn [db [_ chat-id message-id]]
|
||||
(-> db
|
||||
(update-in [chat-id :messages-ids] conj message-id)
|
||||
(update-in [chat-id :count] inc))))
|
||||
|
||||
(register-handler :remove-unviewed-messages
|
||||
(path :unviewed-messages)
|
||||
(fn [db [_ chat-id]]
|
||||
(dissoc db chat-id)))
|
|
@ -68,8 +68,7 @@
|
|||
(dispatch [:proceed-command
|
||||
{:command command,
|
||||
:metadata nil,
|
||||
:args [(get contact :name) amount]}
|
||||
current-chat-id])))))
|
||||
:args [(get contact :name) amount]}])))))
|
||||
|
||||
(defn chat-with-command
|
||||
[_ [_ whisper-identity command-key params]]
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
(ns status-im.chat.models)
|
||||
|
||||
(defn set-chat-ui-props
|
||||
"Updates ui-props in active chat by merging provided kvs into them"
|
||||
[{:keys [current-chat-id] :as db} kvs]
|
||||
(update-in db [:chat-ui-props current-chat-id] merge kvs))
|
||||
|
||||
(defn toggle-chat-ui-prop
|
||||
"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))
|
|
@ -47,13 +47,13 @@
|
|||
{:keys [contacts requests]} (get-in db [:chats chat-id])]
|
||||
(->> contacts
|
||||
(map (fn [{:keys [identity]}]
|
||||
(let [{:keys [commands responses]} (get-in db [:contacts/contacts identity])]
|
||||
(let [commands' (mapv (fn [[k v]] [k [v :any]]) (merge global-commands commands))
|
||||
responses' (mapv (fn [{:keys [message-id type]}]
|
||||
(when-let [response (get responses type)]
|
||||
[type [response message-id]]))
|
||||
requests)]
|
||||
(into commands' responses')))))
|
||||
(let [{:keys [commands responses]} (get-in db [:contacts/contacts identity])]
|
||||
(let [commands' (mapv (fn [[k v]] [k [v :any]]) (merge global-commands commands))
|
||||
responses' (mapv (fn [{:keys [message-id type]}]
|
||||
(when-let [response (get responses type)]
|
||||
[type [response message-id]]))
|
||||
requests)]
|
||||
(into commands' responses')))))
|
||||
(reduce (fn [m cur] (into (or m {}) cur)))
|
||||
(into {}))))
|
||||
|
||||
|
@ -78,7 +78,7 @@
|
|||
(str/replace (str/trim command-text) #" +" " ")
|
||||
command-text)
|
||||
splitted (cond-> (str/split command-text-normalized const/spacing-char)
|
||||
space? (drop-last))]
|
||||
space? (drop-last))]
|
||||
(->> splitted
|
||||
(reduce (fn [[list command-started?] arg]
|
||||
(let [quotes-count (count (filter #(= % const/arg-wrapping-char) arg))
|
||||
|
@ -95,7 +95,7 @@
|
|||
[[] false])
|
||||
(first)))))
|
||||
|
||||
(defn join-command-args [args]
|
||||
(defn join-command-args
|
||||
"Transforms a list of args to a string. The opposite of `split-command-args`.
|
||||
|
||||
Examples:
|
||||
|
@ -107,6 +107,7 @@
|
|||
|
||||
Input: ['/send' 'Complex name with space in between' '1.0']
|
||||
Output: '/send \"Complex name with space in between\" 1.0'"
|
||||
[args]
|
||||
(when args
|
||||
(->> args
|
||||
(map (fn [arg]
|
||||
|
@ -139,13 +140,13 @@
|
|||
(subs command-name 1)))
|
||||
(vals possible-actions))
|
||||
(first))]
|
||||
{:command command
|
||||
:metadata (if (and (nil? (:to-message-id input-metadata)) (not= :any to-message-id))
|
||||
(assoc input-metadata :to-message-id to-message-id)
|
||||
input-metadata)
|
||||
:args (if (empty? seq-arguments)
|
||||
(rest command-args)
|
||||
seq-arguments)}))))
|
||||
{:command command
|
||||
:metadata (if (and (nil? (:to-message-id input-metadata)) (not= :any to-message-id))
|
||||
(assoc input-metadata :to-message-id to-message-id)
|
||||
input-metadata)
|
||||
:args (if (empty? seq-arguments)
|
||||
(rest command-args)
|
||||
seq-arguments)}))))
|
||||
([{:keys [current-chat-id] :as db} chat-id]
|
||||
(selected-chat-command db chat-id (get-in db [:chats chat-id :input-text]))))
|
||||
|
||||
|
@ -178,12 +179,11 @@
|
|||
-1 (`*no-argument-error*`) means error. It can happen if there is no command or selection.
|
||||
|
||||
This method is basically just another way of calling `current-chat-argument-position`."
|
||||
[{:keys [current-chat-id] :as db} chat-id]
|
||||
(let [chat-id (or chat-id current-chat-id)
|
||||
input-text (get-in db [:chats chat-id :input-text])
|
||||
seq-arguments (get-in db [:chats chat-id :seq-arguments])
|
||||
selection (get-in db [:chat-ui-props chat-id :selection])
|
||||
chat-command (selected-chat-command db chat-id)]
|
||||
[{:keys [current-chat-id] :as db}]
|
||||
(let [input-text (get-in db [:chats current-chat-id :input-text])
|
||||
seq-arguments (get-in db [:chats current-chat-id :seq-arguments])
|
||||
selection (get-in db [:chat-ui-props current-chat-id :selection])
|
||||
chat-command (selected-chat-command db current-chat-id)]
|
||||
(current-chat-argument-position chat-command input-text selection seq-arguments)))
|
||||
|
||||
(defn command-completion
|
||||
|
@ -247,12 +247,12 @@
|
|||
prev-command (get-in db [:chat-ui-props current-chat-id :prev-command])]
|
||||
(if command
|
||||
(cond-> db
|
||||
;; clear the bot db
|
||||
(not= prev-command (-> command :command :name))
|
||||
(assoc-in [:bot-db (or (:bot command) current-chat-id)] nil)
|
||||
;; clear the chat's validation messages
|
||||
true
|
||||
(assoc-in [:chat-ui-props current-chat-id :validation-messages] nil))
|
||||
;; clear the bot db
|
||||
(not= prev-command (-> command :command :name))
|
||||
(assoc-in [:bot-db (or (:bot command) current-chat-id)] nil)
|
||||
;; clear the chat's validation messages
|
||||
true
|
||||
(assoc-in [:chat-ui-props current-chat-id :validation-messages] nil))
|
||||
(-> db
|
||||
;; clear input metadata
|
||||
(assoc-in [:chats current-chat-id :input-metadata] nil)
|
||||
|
@ -268,7 +268,7 @@
|
|||
(defmethod validation-handler :phone
|
||||
[_]
|
||||
(fn [[number] error-events-creator]
|
||||
(when-not (phone-number/valid-mobile-number? number)
|
||||
(when-not (phone-number/valid-mobile-number? number)
|
||||
(error-events-creator [validation-message
|
||||
{:title (i18n/label :t/phone-number)
|
||||
:description (i18n/label :t/invalid-phone)}]))))
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
(ns status-im.chat.models.unviewed-messages)
|
||||
|
||||
(defn load-unviewed-messages [db raw-unviewed-messages]
|
||||
(assoc db :unviewed-messages
|
||||
(->> raw-unviewed-messages
|
||||
(group-by :chat-id)
|
||||
(map (fn [[id messages]]
|
||||
[id {:messages-ids (map :message-id messages)
|
||||
:count (count messages)}]))
|
||||
(into {}))))
|
||||
|
||||
(defn add-unviewed-message [db chat-id message-id]
|
||||
(-> db
|
||||
(update-in [:unviewed-messages chat-id :messages-ids] conj message-id)
|
||||
(update-in [:unviewed-messages chat-id :count] inc)))
|
||||
|
||||
(defn remove-unviewed-messages [db chat-id]
|
||||
(update db :unviewed-messages dissoc chat-id))
|
|
@ -1,25 +1,20 @@
|
|||
(ns status-im.chat.sign-up
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[status-im.components.styles :refer [default-chat-color]]
|
||||
[status-im.utils.utils :refer [http-post]]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.sms-listener :refer [add-sms-listener
|
||||
remove-sms-listener]]
|
||||
[status-im.constants :refer [console-chat-id
|
||||
text-content-type
|
||||
content-type-command
|
||||
content-type-command-request
|
||||
content-type-status]]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.constants :as chat-const]
|
||||
[status-im.i18n :refer [label]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(defn send-console-message [text]
|
||||
{:message-id (random/id)
|
||||
:from "me"
|
||||
:to console-chat-id
|
||||
:to const/console-chat-id
|
||||
:content text
|
||||
:content-type text-content-type
|
||||
:content-type const/text-content-type
|
||||
:outgoing true})
|
||||
|
||||
;; todo fn name is not too smart, but...
|
||||
|
@ -29,192 +24,165 @@
|
|||
:content content})
|
||||
|
||||
;; -- Send phone number ----------------------------------------
|
||||
(defn on-sign-up-response [& [message]]
|
||||
(let [message-id (random/id)]
|
||||
(dispatch [:received-message
|
||||
{:message-id message-id
|
||||
:content (command-content
|
||||
:confirmation-code
|
||||
(or message (label :t/confirmation-code)))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])))
|
||||
(defn- confirmation-code-event [correct? message-id]
|
||||
[:received-message
|
||||
{:message-id message-id
|
||||
:content (command-content
|
||||
:confirmation-code
|
||||
(if correct?
|
||||
(label :t/confirmation-code)
|
||||
(label :t/incorrect-code)))
|
||||
:content-type const/content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
|
||||
(defn start-listening-confirmation-code-sms []
|
||||
(dispatch [:request-permissions
|
||||
[:receive-sms]
|
||||
(fn []
|
||||
(let [listener (add-sms-listener
|
||||
(fn [{body :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" body)]
|
||||
(dispatch [:sign-up-confirm (second matches)]))))]
|
||||
(dispatch [:start-listening-confirmation-code-sms listener])))]))
|
||||
(def enter-confirmation-code-event (partial confirmation-code-event true))
|
||||
(def incorrect-confirmation-code-event (partial confirmation-code-event false))
|
||||
|
||||
(defn stop-listening-confirmation-code-sms [db]
|
||||
(when-let [listener (:confirmation-code-sms-listener db)]
|
||||
(remove-sms-listener listener)
|
||||
(dissoc db :confirmation-code-sms-listener)))
|
||||
(defn- sms-receive-handler [{confirmation-code :body}]
|
||||
(when-let [matches (re-matches #"(\d{4})" confirmation-code)]
|
||||
(dispatch [:sign-up-confirm (second matches)])))
|
||||
|
||||
(def start-listening-confirmation-code-sms-event
|
||||
[:request-permissions
|
||||
[:receive-sms]
|
||||
(fn []
|
||||
(let [listener (add-sms-listener sms-receive-handler)]
|
||||
(dispatch [:start-listening-confirmation-code-sms listener])))])
|
||||
|
||||
;; -- Send confirmation code and synchronize contacts---------------------------
|
||||
(defn on-sync-contacts []
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (label :t/contacts-syncronized)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(dispatch [:set-signed-up true]))
|
||||
(defn contacts-synchronised-event [message-id]
|
||||
[:received-message
|
||||
{:message-id message-id
|
||||
:content (label :t/contacts-syncronized)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
|
||||
(defn sync-contacts []
|
||||
;; TODO 'on-sync-contacts' is never called
|
||||
(dispatch [:request-permissions
|
||||
[:read-contacts]
|
||||
#(dispatch [:sync-contacts on-sync-contacts])]))
|
||||
|
||||
(defn on-send-code-response [body]
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (:message body)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(let [status (keyword (:status body))]
|
||||
(when (= :confirmed status)
|
||||
(dispatch [:stop-listening-confirmation-code-sms])
|
||||
(sync-contacts)
|
||||
;; TODO should be called after sync-contacts?
|
||||
(dispatch [:set-signed-up true]))
|
||||
(when (= :failed status)
|
||||
(on-sign-up-response (label :t/incorrect-code)))))
|
||||
|
||||
(defn start-signup []
|
||||
(let [message-id (random/id)]
|
||||
(dispatch [:received-message
|
||||
{:message-id message-id
|
||||
:content (command-content
|
||||
:phone
|
||||
(label :t/phone-number-required))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content (label :t/shake-your-phone)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(def start-signup-events
|
||||
[[:received-message
|
||||
{:message-id (random/id)
|
||||
:content (command-content
|
||||
:phone
|
||||
(label :t/phone-number-required))
|
||||
:content-type const/content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]
|
||||
[:received-message
|
||||
{:message-id (random/id)
|
||||
:content (label :t/shake-your-phone)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]])
|
||||
|
||||
;; -- Saving password ----------------------------------------
|
||||
(defn account-generation-message []
|
||||
(dispatch [:received-message
|
||||
{:message-id const/crazy-math-message-id
|
||||
:content (label :t/account-generation-message)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(def account-generation-event
|
||||
[:received-message
|
||||
{:message-id chat-const/crazy-math-message-id
|
||||
:content (label :t/account-generation-message)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
|
||||
(defn move-to-internal-failure-message []
|
||||
(dispatch [:received-message
|
||||
{:message-id const/move-to-internal-failure-message-id
|
||||
:content (command-content
|
||||
:grant-permissions
|
||||
(label :t/move-to-internal-failure-message))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(def move-to-internal-failure-event
|
||||
[:received-message
|
||||
{:message-id chat-const/move-to-internal-failure-message-id
|
||||
:content (command-content
|
||||
:grant-permissions
|
||||
(label :t/move-to-internal-failure-message))
|
||||
:content-type const/content-type-command-request
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}])
|
||||
|
||||
|
||||
(defn passphrase-messages [mnemonic signing-phrase crazy-math-message?]
|
||||
(dispatch [:received-message
|
||||
{:message-id const/passphrase-message-id
|
||||
:content (if crazy-math-message?
|
||||
(label :t/phew-here-is-your-passphrase)
|
||||
(label :t/here-is-your-passphrase))
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content mnemonic
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(dispatch [:received-message
|
||||
{:message-id const/signing-phrase-message-id
|
||||
:content (label :t/here-is-your-signing-phrase)
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(dispatch [:received-message
|
||||
{:message-id (random/id)
|
||||
:content signing-phrase
|
||||
:content-type text-content-type
|
||||
:outgoing false
|
||||
:chat-id console-chat-id
|
||||
:from console-chat-id
|
||||
:to "me"}])
|
||||
(start-signup))
|
||||
(defn passphrase-messages-events [mnemonic signing-phrase crazy-math-message?]
|
||||
(into [[:received-message
|
||||
{:message-id chat-const/passphrase-message-id
|
||||
:content (if crazy-math-message?
|
||||
(label :t/phew-here-is-your-passphrase)
|
||||
(label :t/here-is-your-passphrase))
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]
|
||||
[:received-message
|
||||
{:message-id (random/id)
|
||||
:content mnemonic
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]
|
||||
[:received-message
|
||||
{:message-id chat-const/signing-phrase-message-id
|
||||
:content (label :t/here-is-your-signing-phrase)
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]
|
||||
[:received-message
|
||||
{:message-id (random/id)
|
||||
:content signing-phrase
|
||||
:content-type const/text-content-type
|
||||
:outgoing false
|
||||
:chat-id const/console-chat-id
|
||||
:from const/console-chat-id
|
||||
:to "me"}]]
|
||||
start-signup-events))
|
||||
|
||||
(def intro-status
|
||||
{:message-id const/intro-status-message-id
|
||||
{:message-id chat-const/intro-status-message-id
|
||||
:content (label :t/intro-status)
|
||||
:from console-chat-id
|
||||
:chat-id console-chat-id
|
||||
:content-type content-type-status
|
||||
:from const/console-chat-id
|
||||
:chat-id const/console-chat-id
|
||||
:content-type const/content-type-status
|
||||
:outgoing false
|
||||
:to "me"})
|
||||
|
||||
(defn intro []
|
||||
(dispatch [:received-message intro-status])
|
||||
(dispatch [:received-message-when-commands-loaded
|
||||
console-chat-id
|
||||
{:chat-id console-chat-id
|
||||
:message-id const/intro-message1-id
|
||||
:content (command-content
|
||||
:password
|
||||
(label :t/intro-message1))
|
||||
:content-type content-type-command-request
|
||||
:outgoing false
|
||||
:from console-chat-id
|
||||
:to "me"}]))
|
||||
(def intro-events
|
||||
[[:received-message intro-status]
|
||||
[:received-message-when-commands-loaded
|
||||
const/console-chat-id
|
||||
{:chat-id const/console-chat-id
|
||||
:message-id chat-const/intro-message1-id
|
||||
:content (command-content
|
||||
:password
|
||||
(label :t/intro-message1))
|
||||
:content-type const/content-type-command-request
|
||||
:outgoing false
|
||||
:from const/console-chat-id
|
||||
:to "me"}]])
|
||||
|
||||
(def console-chat
|
||||
{:chat-id console-chat-id
|
||||
:name (s/capitalize console-chat-id)
|
||||
{:chat-id const/console-chat-id
|
||||
:name (s/capitalize const/console-chat-id)
|
||||
:color default-chat-color
|
||||
:group-chat false
|
||||
:is-active true
|
||||
:unremovable? true
|
||||
:timestamp (.getTime (js/Date.))
|
||||
:photo-path console-chat-id
|
||||
:contacts [{:identity console-chat-id
|
||||
:photo-path const/console-chat-id
|
||||
:contacts [{:identity const/console-chat-id
|
||||
:text-color "#FFFFFF"
|
||||
:background-color "#AB7967"}]})
|
||||
|
||||
(def console-contact
|
||||
{:whisper-identity console-chat-id
|
||||
:name (s/capitalize console-chat-id)
|
||||
:photo-path console-chat-id
|
||||
{:whisper-identity const/console-chat-id
|
||||
:name (s/capitalize const/console-chat-id)
|
||||
:photo-path const/console-chat-id
|
||||
:dapp? true
|
||||
:unremovable? true
|
||||
:bot-url "local://console-bot"
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [reagent.core :as r]
|
||||
[re-frame.core :refer [dispatch subscribe]]
|
||||
[clojure.string :as str]
|
||||
[status-im.chat.constants :as const]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
list-view
|
||||
|
@ -12,20 +10,15 @@
|
|||
[status-im.components.renderers.renderers :as renderers]
|
||||
[status-im.utils.listview :as lw]))
|
||||
|
||||
(defn- select-contact [arg-index bot-db-key {:keys [name] :as contact}]
|
||||
(let [contact (select-keys contact [:address :whisper-identity :name :photo-path :dapp?])
|
||||
name (str/replace name (re-pattern const/arg-wrapping-char) "")]
|
||||
(dispatch [:set-command-argument [arg-index name true]])
|
||||
(dispatch [:set-in-bot-db {:path [:public (keyword bot-db-key)]
|
||||
:value contact}])
|
||||
(dispatch [:select-next-argument])))
|
||||
|
||||
(defn render-row [arg-index bot-db-key]
|
||||
(fn [contact _ _]
|
||||
(list-item
|
||||
^{:key contact}
|
||||
[contact-view {:contact contact
|
||||
:on-press #(select-contact arg-index bot-db-key contact)}])))
|
||||
^{:key contact}
|
||||
[contact-view {:contact contact
|
||||
:on-press #(dispatch
|
||||
[:set-contact-as-command-argument {:arg-index arg-index
|
||||
:bot-db-key bot-db-key
|
||||
:contact contact}])}])))
|
||||
|
||||
(defview choose-contact-view [{title :title
|
||||
arg-index :index
|
||||
|
@ -44,4 +37,4 @@
|
|||
:renderRow (render-row arg-index bot-db-key)
|
||||
:bounces false
|
||||
:keyboardShouldPersistTaps :always
|
||||
:renderSeparator renderers/list-separator-renderer}]])
|
||||
:renderSeparator renderers/list-separator-renderer}]])
|
||||
|
|
|
@ -41,9 +41,7 @@
|
|||
show-suggestions? [:show-suggestions?]]
|
||||
[view style/commands-root
|
||||
[view style/command-list-icon-container
|
||||
[touchable-highlight {:on-press #(do (dispatch [:toggle-chat-ui-props :show-suggestions?])
|
||||
(dispatch [:set-chat-ui-props {:validation-messages nil}])
|
||||
(dispatch [:update-suggestions]))}
|
||||
[touchable-highlight {:on-press #(dispatch [:show-suggestions])}
|
||||
[view style/commands-list-icon
|
||||
(if show-suggestions?
|
||||
[vi/icon :icons/close]
|
||||
|
@ -103,8 +101,8 @@
|
|||
(.-height))]
|
||||
(set-layout-height-fn h)))
|
||||
:on-selection-change #(let [s (-> (.-nativeEvent %)
|
||||
(.-selection))
|
||||
end (.-end s)]
|
||||
(.-selection))
|
||||
end (.-end s)]
|
||||
(dispatch [:update-text-selection end]))
|
||||
:style (style/input-view height single-line-input?)
|
||||
:placeholder-text-color style/color-input-helper-placeholder
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
get-contact-translated]]
|
||||
[status-im.chat.utils :as cu]
|
||||
[clojure.string :as str]
|
||||
[status-im.chat.handlers.console :as console]
|
||||
[status-im.chat.events.console :as console]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def window-width (:width (get-dimensions "window")))
|
||||
|
@ -299,9 +299,8 @@
|
|||
(defview message-delivery-status
|
||||
[{:keys [message-id chat-id message-status user-statuses content]}]
|
||||
[app-db-message-status-value [:get-in [:message-data :statuses message-id :status]]]
|
||||
(let [delivery-status (get-in user-statuses [chat-id :status])
|
||||
command-name (keyword (:command content))
|
||||
status (cond (and (not (console/commands-with-delivery-status command-name))
|
||||
(let [delivery-status (get-in user-statuses [chat-id :status])
|
||||
status (cond (and (not (console/commands-with-delivery-status (:command content)))
|
||||
(cu/console? chat-id))
|
||||
:seen
|
||||
|
||||
|
|
|
@ -122,4 +122,4 @@
|
|||
{:sections (clj->js (map wrap-per-section-render-fn sections))
|
||||
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)}
|
||||
(when p/ios? {:SectionSeparatorComponent (fn [] (r/as-element [section-separator]))})
|
||||
props)]))
|
||||
props)]))
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
(defn- command-type?
|
||||
[type]
|
||||
(contains?
|
||||
#{c/content-type-command c/content-type-command-request
|
||||
c/content-type-wallet-request c/content-type-wallet-command}
|
||||
type))
|
||||
#{c/content-type-command c/content-type-command-request
|
||||
c/content-type-wallet-request c/content-type-wallet-command}
|
||||
type))
|
||||
|
||||
(def default-values
|
||||
{:outgoing false
|
||||
|
@ -97,6 +97,14 @@
|
|||
[]
|
||||
(data-store/get-unviewed))
|
||||
|
||||
(defn get-previews
|
||||
[]
|
||||
(->> (data-store/get-all-as-list)
|
||||
(filter :preview)
|
||||
(reduce (fn [acc {:keys [message-id preview]}]
|
||||
(assoc acc message-id (read-string preview)))
|
||||
{})))
|
||||
|
||||
(defn save
|
||||
;; todo remove chat-id parameter
|
||||
[chat-id {:keys [message-id content]
|
||||
|
@ -112,7 +120,7 @@
|
|||
:timestamp (timestamp)})]
|
||||
(data-store/save message'))))
|
||||
|
||||
(defn update
|
||||
(defn update
|
||||
[{:keys [message-id] :as message}]
|
||||
(when (data-store/exists? message-id)
|
||||
(let [message (update-if-present message :user-statuses vals)]
|
||||
|
@ -120,4 +128,3 @@
|
|||
|
||||
(defn delete-by-chat-id [chat-id]
|
||||
(data-store/delete-by-chat-id chat-id))
|
||||
|
||||
|
|
|
@ -1,38 +1,47 @@
|
|||
(ns status-im.ui.screens.accounts.events
|
||||
(:require
|
||||
status-im.ui.screens.accounts.login.events
|
||||
status-im.ui.screens.accounts.recover.events
|
||||
status-im.ui.screens.accounts.login.events
|
||||
status-im.ui.screens.accounts.recover.events
|
||||
|
||||
[status-im.data-store.accounts :as accounts-store]
|
||||
[re-frame.core :refer [reg-cofx reg-fx dispatch inject-cofx]]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
[status-im.utils.identicon :refer [identicon]]
|
||||
[status-im.utils.random :as random]
|
||||
[clojure.string :as str]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.handlers :refer [register-handler-db register-handler-fx get-hashtags] :as handlers]
|
||||
[status-im.ui.screens.accounts.statuses :as statuses]
|
||||
[status-im.utils.signing-phrase.core :as signing-phrase]
|
||||
[status-im.utils.gfycat.core :refer [generate-gfy]]))
|
||||
[status-im.data-store.accounts :as accounts-store]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
[status-im.utils.identicon :refer [identicon]]
|
||||
[status-im.utils.random :as random]
|
||||
[clojure.string :as str]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.ui.screens.accounts.statuses :as statuses]
|
||||
[status-im.utils.signing-phrase.core :as signing-phrase]
|
||||
[status-im.utils.gfycat.core :refer [generate-gfy]]))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn create-account
|
||||
"Takes db and password, creates map of effects describing account creation"
|
||||
[db password]
|
||||
{:db (assoc db :accounts/creating-account? true)
|
||||
::create-account password
|
||||
:dispatch-later [{:ms 400 :dispatch [:account-generation-message]}]})
|
||||
|
||||
;;;; COFX
|
||||
|
||||
(reg-cofx
|
||||
:get-new-keypair!
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :keypair (protocol/new-keypair!))))
|
||||
(re-frame/reg-cofx
|
||||
:get-new-keypair!
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :keypair (protocol/new-keypair!))))
|
||||
|
||||
(reg-cofx
|
||||
::get-all-accounts
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :all-accounts (accounts-store/get-all))))
|
||||
(re-frame/reg-cofx
|
||||
::get-all-accounts
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :all-accounts (accounts-store/get-all))))
|
||||
|
||||
;;;; FX
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::save-account
|
||||
(fn [account]
|
||||
(accounts-store/save account true)))
|
||||
|
@ -55,46 +64,46 @@
|
|||
:signing-phrase phrase}]
|
||||
(log/debug "account-created")
|
||||
(when-not (str/blank? public-key)
|
||||
(dispatch [:show-mnemonic mnemonic phrase])
|
||||
(dispatch [:add-account account password]))))
|
||||
(re-frame/dispatch [:show-mnemonic mnemonic phrase])
|
||||
(re-frame/dispatch [:add-account account password]))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::create-account
|
||||
(fn [password]
|
||||
(status/create-account
|
||||
password
|
||||
#(account-created % password))))
|
||||
password
|
||||
#(account-created % password))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::broadcast-account-update
|
||||
(fn [{:keys [current-public-key web3 name photo-path status
|
||||
updates-public-key updates-private-key]}]
|
||||
(when web3
|
||||
(protocol/broadcast-profile!
|
||||
{:web3 web3
|
||||
:message {:from current-public-key
|
||||
:message-id (random/id)
|
||||
:keypair {:public updates-public-key
|
||||
:private updates-private-key}
|
||||
:payload {:profile {:name name
|
||||
:status status
|
||||
:profile-image photo-path}}}}))))
|
||||
{:web3 web3
|
||||
:message {:from current-public-key
|
||||
:message-id (random/id)
|
||||
:keypair {:public updates-public-key
|
||||
:private updates-private-key}
|
||||
:payload {:profile {:name name
|
||||
:status status
|
||||
:profile-image photo-path}}}}))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::send-keys-update
|
||||
(fn [{:keys [web3 current-public-key contacts
|
||||
updates-public-key updates-private-key]}]
|
||||
(doseq [id (handlers/identities contacts)]
|
||||
(protocol/update-keys!
|
||||
{:web3 web3
|
||||
:message {:from current-public-key
|
||||
:to id
|
||||
:message-id (random/id)
|
||||
:payload {:keypair {:public updates-public-key
|
||||
:private updates-private-key}}}}))))
|
||||
{:web3 web3
|
||||
:message {:from current-public-key
|
||||
:to id
|
||||
:message-id (random/id)
|
||||
:payload {:keypair {:public updates-public-key
|
||||
:private updates-private-key}}}}))))
|
||||
;;;; Handlers
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:add-account
|
||||
(fn [{{:keys [network]
|
||||
:networks/keys [networks]
|
||||
|
@ -107,23 +116,16 @@
|
|||
(when password
|
||||
{:dispatch-later [{:ms 400 :dispatch [:login-account address password true]}]})))))
|
||||
|
||||
(register-handler-fx
|
||||
:create-account
|
||||
(fn [{db :db} [_ password]]
|
||||
{:db (assoc db :accounts/creating-account? true)
|
||||
::create-account password
|
||||
:dispatch-later [{:ms 400 :dispatch [:account-generation-message]}]}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:create-new-account-handler
|
||||
(fn [_ _]
|
||||
{:dispatch-n [[:initialize-db]
|
||||
[:load-accounts]
|
||||
[:check-console-chat true]]}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:load-accounts
|
||||
[(inject-cofx ::get-all-accounts)]
|
||||
[(re-frame/inject-cofx ::get-all-accounts)]
|
||||
(fn [{:keys [db all-accounts]} _]
|
||||
(let [accounts (->> all-accounts
|
||||
(map (fn [{:keys [address] :as account}]
|
||||
|
@ -136,7 +138,7 @@
|
|||
(when-not (empty? events)
|
||||
{:dispatch-n events})))))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:account-update-networks
|
||||
(fn [{{:accounts/keys [accounts] :networks/keys [networks] :as db} :db} [_ id]]
|
||||
(let [current-account (get accounts id)
|
||||
|
@ -144,41 +146,51 @@
|
|||
{:db (assoc-in db [:accounts/accounts id] new-account)
|
||||
::save-account new-account})))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:check-status-change
|
||||
(fn [{{:accounts/keys [accounts current-account-id]} :db} [_ status]]
|
||||
(let [{old-status :status} (get accounts current-account-id)
|
||||
status-updated? (and (not= status nil)
|
||||
(not= status old-status))]
|
||||
(when status-updated?
|
||||
(let [hashtags (get-hashtags status)]
|
||||
(let [hashtags (handlers/get-hashtags status)]
|
||||
(when (seq hashtags)
|
||||
{:dispatch [:broadcast-status status hashtags]}))))))
|
||||
|
||||
(defn update-account [current-account new-fields]
|
||||
(merge current-account (assoc new-fields :last-updated (time/now-ms))))
|
||||
(defn- update-account [current-account new-fields now]
|
||||
(merge current-account (assoc new-fields :last-updated now)))
|
||||
|
||||
(register-handler-fx
|
||||
(defn account-update
|
||||
"Takes map of coeffects containing `:db` and `:now` keys + new account fields,
|
||||
returns all effects necessary for account update."
|
||||
[{{:keys [network]
|
||||
:accounts/keys [accounts current-account-id] :as db} :db now :now} new-account-fields]
|
||||
(let [current-account (get accounts current-account-id)
|
||||
new-account (update-account current-account new-account-fields now)]
|
||||
{:db (assoc-in db [:accounts/accounts current-account-id] new-account)
|
||||
::save-account new-account
|
||||
::broadcast-account-update (merge
|
||||
(select-keys db [:current-public-key :web3])
|
||||
(select-keys new-account [:name :photo-path :status
|
||||
:updates-public-key :updates-private-key]))}))
|
||||
|
||||
;; TODO(janherich): remove this event once it's not used anymore
|
||||
(handlers/register-handler-fx
|
||||
:account-update
|
||||
(fn [{{:accounts/keys [accounts current-account-id] :as db} :db} [_ new-account-fields]]
|
||||
(let [current-account (get accounts current-account-id)
|
||||
new-account (update-account current-account new-account-fields)]
|
||||
{:db (assoc-in db [:accounts/accounts current-account-id] new-account)
|
||||
::save-account new-account
|
||||
::broadcast-account-update (merge
|
||||
(select-keys db [:current-public-key :web3])
|
||||
(select-keys new-account [:name :photo-path :status
|
||||
:updates-public-key :updates-private-key]))})))
|
||||
[(re-frame/inject-cofx :now) re-frame/trim-v]
|
||||
(fn [cofx [new-account-fields]]
|
||||
(account-update cofx new-account-fields)))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:account-update-keys
|
||||
[(inject-cofx :get-new-keypair!)]
|
||||
(fn [{:keys [db keypair]} _]
|
||||
[(re-frame/inject-cofx :get-new-keypair!) (re-frame/inject-cofx :now)]
|
||||
(fn [{:keys [db keypair now]} _]
|
||||
(let [{:accounts/keys [accounts current-account-id]} db
|
||||
{:keys [public private]} keypair
|
||||
current-account (get accounts current-account-id)
|
||||
new-account (update-account current-account {:updates-public-key public
|
||||
:updates-private-key private})]
|
||||
:updates-private-key private}
|
||||
now)]
|
||||
{:db (assoc-in db [:accounts/accounts current-account-id] new-account)
|
||||
::save-account new-account
|
||||
::send-keys-update (merge
|
||||
|
@ -186,17 +198,19 @@
|
|||
(select-keys new-account [:updates-public-key
|
||||
:updates-private-key]))})))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:send-account-update-if-needed
|
||||
(fn [{{:accounts/keys [accounts current-account-id]} :db} _]
|
||||
[(re-frame/inject-cofx :now)]
|
||||
(fn [{{:accounts/keys [accounts current-account-id]} :db now :now :as cofx} _]
|
||||
(let [{:keys [last-updated]} (get accounts current-account-id)
|
||||
now (time/now-ms)
|
||||
needs-update? (> (- now last-updated) time/week)]
|
||||
(log/info "Need to send account-update: " needs-update?)
|
||||
(when needs-update?
|
||||
(dispatch [:account-update])))))
|
||||
;; TODO(janherich): this is very strange and misleading, need to figure out why it'd necessary to update
|
||||
;; account with network update when last update was more then week ago
|
||||
(account-update cofx nil)))))
|
||||
|
||||
(register-handler-db
|
||||
(handlers/register-handler-db
|
||||
:set-current-account
|
||||
(fn [{:accounts/keys [accounts] :as db} [_ address]]
|
||||
(let [key (:public-key (accounts address))]
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
(fn []
|
||||
(when (and (get-in @message [:content :command])
|
||||
(not @preview))
|
||||
(dispatch [:request-command-data @message :short-preview])))
|
||||
(dispatch [:request-command-message-data @message :short-preview])))
|
||||
|
||||
:reagent-render
|
||||
(fn [_]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.ui.screens.contacts.events
|
||||
(:require [re-frame.core :refer [dispatch reg-fx reg-cofx inject-cofx]]
|
||||
(:require [re-frame.core :refer [dispatch trim-v reg-fx reg-cofx inject-cofx]]
|
||||
[status-im.utils.handlers :refer [register-handler-db register-handler-fx]]
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.utils.crypt :refer [encrypt]]
|
||||
|
@ -22,15 +22,15 @@
|
|||
;;;; COFX
|
||||
|
||||
(reg-cofx
|
||||
::get-all-contacts
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :all-contacts (contacts/get-all))))
|
||||
::get-all-contacts
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :all-contacts (contacts/get-all))))
|
||||
|
||||
(reg-cofx
|
||||
::get-default-contacts-and-groups
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :default-contacts js-res/default-contacts
|
||||
:default-groups js-res/default-contact-groups)))
|
||||
::get-default-contacts-and-groups
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :default-contacts js-res/default-contacts
|
||||
:default-groups js-res/default-contact-groups)))
|
||||
|
||||
;;;; FX
|
||||
|
||||
|
@ -102,13 +102,13 @@
|
|||
|
||||
(reg-fx
|
||||
::fetch-contacts-from-phone!
|
||||
(fn [_]
|
||||
(fn [on-contacts-event-creator]
|
||||
(.getAll rn-dependencies/contacts
|
||||
(fn [error contacts]
|
||||
(if error
|
||||
(log/debug :error-on-fetching-loading error)
|
||||
(let [contacts' (normalize-phone-contacts contacts)]
|
||||
(dispatch [::get-contacts-identities contacts'])))))))
|
||||
(dispatch [::get-contacts-identities contacts' on-contacts-event-creator])))))))
|
||||
|
||||
(defn- get-contacts-by-hash [contacts]
|
||||
(->> contacts
|
||||
|
@ -126,18 +126,17 @@
|
|||
(map (fn [{:keys [phone-number-hash whisper-identity address]}]
|
||||
(let [contact (contacts-by-hash phone-number-hash)]
|
||||
(assoc contact :whisper-identity whisper-identity
|
||||
:address address)))
|
||||
:address address)))
|
||||
(js->clj contacts)))
|
||||
|
||||
(reg-fx
|
||||
::request-stored-contacts
|
||||
(fn [contacts]
|
||||
(fn [{:keys [contacts on-contacts-event-creator]}]
|
||||
(let [contacts-by-hash (get-contacts-by-hash contacts)
|
||||
data (or (keys contacts-by-hash) '())]
|
||||
(http-post "get-contacts" {:phone-number-hashes data}
|
||||
(fn [{:keys [contacts]}]
|
||||
(let [contacts' (add-identity contacts-by-hash contacts)]
|
||||
(dispatch [:add-contacts contacts'])))))))
|
||||
(dispatch (on-contacts-event-creator (add-identity contacts-by-hash contacts))))))))
|
||||
|
||||
(reg-fx
|
||||
::request-contacts-by-address
|
||||
|
@ -159,16 +158,24 @@
|
|||
|
||||
(register-handler-fx
|
||||
::get-contacts-identities
|
||||
(fn [_ [_ contacts]]
|
||||
{::request-stored-contacts contacts}))
|
||||
[trim-v]
|
||||
(fn [_ [contacts on-contacts-event-creator]]
|
||||
{::request-stored-contacts {:contacts contacts
|
||||
:on-contacts-event-creator on-contacts-event-creator}}))
|
||||
|
||||
(register-handler-fx
|
||||
:sync-contacts
|
||||
[trim-v]
|
||||
(fn [_ [on-contacts-event-creator]]
|
||||
{::fetch-contacts-from-phone! on-contacts-event-creator}))
|
||||
|
||||
(register-handler-fx
|
||||
:watch-contact
|
||||
(fn [{:keys [db]} [_ {:keys [public-key private-key] :as contact}]]
|
||||
(when (and public-key private-key)
|
||||
{::watch-contact (merge
|
||||
(select-keys db [:web3])
|
||||
(select-keys contact [:whisper-identity :public-key :private-key]))})))
|
||||
(select-keys db [:web3])
|
||||
(select-keys contact [:whisper-identity :public-key :private-key]))})))
|
||||
|
||||
(register-handler-fx
|
||||
:update-contact!
|
||||
|
@ -177,11 +184,6 @@
|
|||
{:db (update-in db [:contacts/contacts whisper-identity] merge contact)
|
||||
::save-contact contact})))
|
||||
|
||||
(register-handler-fx
|
||||
:sync-contacts
|
||||
(fn [_ _]
|
||||
{::fetch-contacts-from-phone! nil}))
|
||||
|
||||
(defn- update-pending-status [old-contacts {:keys [whisper-identity pending?] :as contact}]
|
||||
(let [{old-pending :pending?
|
||||
:as old-contact} (get old-contacts whisper-identity)
|
||||
|
@ -209,7 +211,7 @@
|
|||
:timestamp (random/timestamp)
|
||||
:contacts (mapv #(hash-map :identity %) contacts)})]])
|
||||
|
||||
(defn- prepare-default-contacts-events [contacts default-contacts]
|
||||
(defn- prepare-default-contacts-events [contacts default-contacts]
|
||||
[[:add-contacts
|
||||
(for [[id {:keys [name photo-path public-key add-chat? global-command
|
||||
dapp? dapp-url dapp-hash bot-url unremovable?]}] default-contacts
|
||||
|
@ -257,11 +259,11 @@
|
|||
(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-bot-commands-events contacts default-contacts)
|
||||
(prepare-add-contacts-to-groups-events contacts default-contacts))})))
|
||||
(prepare-default-groups-events contact-groups default-groups)
|
||||
(prepare-default-contacts-events contacts default-contacts)
|
||||
(prepare-add-chat-events contacts default-contacts)
|
||||
(prepare-bot-commands-events contacts default-contacts)
|
||||
(prepare-add-contacts-to-groups-events contacts default-contacts))})))
|
||||
|
||||
(register-handler-fx
|
||||
:load-contacts
|
||||
|
@ -278,30 +280,36 @@
|
|||
(into {}))
|
||||
contacts (into {} contacts-list)]
|
||||
{:db (assoc db :contacts/contacts contacts
|
||||
:global-commands global-commands)
|
||||
:global-commands global-commands)
|
||||
:dispatch-n (mapv (fn [_ contact] [:watch-contact contact]) contacts)})))
|
||||
|
||||
(defn add-contacts
|
||||
"Creates effects map for adding contacts"
|
||||
[db new-contacts]
|
||||
(let [{:contacts/keys [contacts]} db
|
||||
identities (set (keys contacts))
|
||||
new-contacts' (->> new-contacts
|
||||
(map #(update-pending-status contacts %))
|
||||
(remove #(identities (:whisper-identity %)))
|
||||
(map #(vector (:whisper-identity %) %))
|
||||
(into {}))
|
||||
global-commands (->> new-contacts'
|
||||
(keep (fn [[n {:keys [global-command]}]]
|
||||
(when global-command
|
||||
[(keyword n) (assoc global-command
|
||||
:type :command
|
||||
:bot n)])))
|
||||
(into {}))]
|
||||
{:db (-> db
|
||||
(update :global-commands merge global-commands)
|
||||
(update :contacts/contacts merge new-contacts'))
|
||||
::save-contacts! (vals new-contacts')}))
|
||||
|
||||
(register-handler-fx
|
||||
:add-contacts
|
||||
(fn [{:keys [db]} [_ new-contacts]]
|
||||
(let [{:contacts/keys [contacts]} db
|
||||
identities (set (keys contacts))
|
||||
new-contacts' (->> new-contacts
|
||||
(map #(update-pending-status contacts %))
|
||||
(remove #(identities (:whisper-identity %)))
|
||||
(map #(vector (:whisper-identity %) %))
|
||||
(into {}))
|
||||
global-commands (->> new-contacts'
|
||||
(keep (fn [[n {:keys [global-command]}]]
|
||||
(when global-command
|
||||
[(keyword n) (assoc global-command
|
||||
:type :command
|
||||
:bot n)])))
|
||||
(into {}))]
|
||||
{:db (-> db
|
||||
(update :global-commands merge global-commands)
|
||||
(update :contacts/contacts merge new-contacts'))
|
||||
::save-contacts! (vals new-contacts')})))
|
||||
[trim-v]
|
||||
(fn [{:keys [db]} [new-contacts]]
|
||||
(add-contacts db new-contacts)))
|
||||
|
||||
(register-handler-db
|
||||
:remove-contacts-click-handler
|
||||
|
@ -347,7 +355,7 @@
|
|||
(read-string contact-info)
|
||||
(get contacts chat-or-whisper-id))
|
||||
contact' (assoc contact :address (public-key->address chat-or-whisper-id)
|
||||
:pending? false)]
|
||||
:pending? false)]
|
||||
{:dispatch-n [[::add-new-contact contact']
|
||||
[:watch-contact contact']
|
||||
[:discoveries-send-portions chat-or-whisper-id]]})))
|
||||
|
@ -403,8 +411,8 @@
|
|||
:hide-contact
|
||||
(fn [{:keys [db]} [_ {:keys [whisper-identity] :as contact}]]
|
||||
{::stop-watching-contact (merge
|
||||
(select-keys db [:web3])
|
||||
(select-keys contact [:whisper-identity]))
|
||||
(select-keys db [:web3])
|
||||
(select-keys contact [:whisper-identity]))
|
||||
:dispatch-n [[:update-contact! {:whisper-identity whisper-identity
|
||||
:pending? true}]
|
||||
[:account-update-keys]]}))
|
||||
|
@ -433,10 +441,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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.ui.screens.events
|
||||
(:require status-im.bots.handlers
|
||||
(:require status-im.bots.events
|
||||
status-im.chat.handlers
|
||||
status-im.commands.handlers.jail
|
||||
status-im.commands.handlers.loading
|
||||
|
@ -17,7 +17,7 @@
|
|||
status-im.ui.screens.profile.events
|
||||
status-im.ui.screens.qr-scanner.events
|
||||
status-im.ui.screens.wallet.events
|
||||
[re-frame.core :refer [dispatch reg-fx]]
|
||||
[re-frame.core :refer [dispatch reg-fx reg-cofx]]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.components.permissions :as permissions]
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
|
@ -25,6 +25,9 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.js-dependencies :as dependencies]
|
||||
[status-im.ui.screens.db :refer [app-db]]
|
||||
[status-im.utils.sms-listener :as sms-listener-util]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.crypt :as crypt]
|
||||
[status-im.utils.notifications :as notifications]
|
||||
|
@ -35,10 +38,87 @@
|
|||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;;;; Helper fns
|
||||
|
||||
(defn- call-jail-function
|
||||
[{:keys [chat-id function callback-events-creator] :as opts}]
|
||||
(let [path [:functions function]
|
||||
params (select-keys opts [:parameters :context])]
|
||||
(status/call-jail
|
||||
{:jail-id chat-id
|
||||
:path path
|
||||
:params params
|
||||
:callback (fn [jail-response]
|
||||
(doseq [event (if callback-events-creator
|
||||
(callback-events-creator jail-response)
|
||||
[[:received-bot-response
|
||||
{:chat-id chat-id}
|
||||
jail-response]])
|
||||
:when event]
|
||||
(dispatch event)))})))
|
||||
|
||||
;;;; COFX
|
||||
|
||||
(reg-cofx
|
||||
:now
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :now (time/now-ms))))
|
||||
|
||||
(reg-cofx
|
||||
:random-id
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :random-id (random/id))))
|
||||
|
||||
(reg-cofx
|
||||
:random-id-seq
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :random-id-seq
|
||||
((fn rand-id-seq []
|
||||
(cons (random/id) (lazy-seq (rand-id-seq))))))))
|
||||
|
||||
;;;; FX
|
||||
|
||||
(reg-fx
|
||||
:call-jail
|
||||
(fn [{:keys [callback-events-creator] :as opts}]
|
||||
(status/call-jail
|
||||
(-> opts
|
||||
(dissoc :callback-events-creator)
|
||||
(assoc :callback
|
||||
(fn [jail-response]
|
||||
(doseq [event (callback-events-creator jail-response)]
|
||||
(dispatch event))))))))
|
||||
|
||||
(reg-fx
|
||||
:call-jail-function
|
||||
call-jail-function)
|
||||
|
||||
(reg-fx
|
||||
:call-jail-function-n
|
||||
(fn [opts-seq]
|
||||
(doseq [opts opts-seq]
|
||||
(call-jail-function opts))))
|
||||
|
||||
(reg-fx
|
||||
:http-post
|
||||
(fn [{:keys [action data success-event-creator failure-event-creator]}]
|
||||
(utils/http-post action
|
||||
data
|
||||
#(dispatch (success-event-creator %))
|
||||
#(dispatch (failure-event-creator %)))))
|
||||
|
||||
(reg-fx
|
||||
:http-get
|
||||
(fn [{:keys [url success-event-creator failure-event-creator]}]
|
||||
(utils/http-get url
|
||||
#(dispatch (success-event-creator %))
|
||||
#(dispatch (failure-event-creator %)))))
|
||||
|
||||
(reg-fx
|
||||
:remove-sms-listener
|
||||
(fn [subscription]
|
||||
(sms-listener-util/remove-sms-listener subscription)))
|
||||
|
||||
(reg-fx
|
||||
::init-store
|
||||
(fn []
|
||||
|
@ -101,9 +181,9 @@
|
|||
(i18n/label :testfairy-message)))))
|
||||
|
||||
(reg-fx
|
||||
::get-fcm-token-fx
|
||||
(fn []
|
||||
(notifications/get-fcm-token)))
|
||||
::get-fcm-token-fx
|
||||
(fn []
|
||||
(notifications/get-fcm-token)))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
|
@ -211,9 +291,9 @@
|
|||
(.geoPermissionsGranted webview-bridge)))
|
||||
|
||||
(register-handler-fx
|
||||
:get-fcm-token
|
||||
(fn [_ _]
|
||||
{::get-fcm-token-fx nil}))
|
||||
:get-fcm-token
|
||||
(fn [_ _]
|
||||
{::get-fcm-token-fx nil}))
|
||||
|
||||
(defn handle-jail-signal [{:keys[chat_id data]}]
|
||||
(let [{:keys [event data]} (types/json->clj data)]
|
||||
|
|
|
@ -95,4 +95,4 @@
|
|||
(-> db
|
||||
(assoc :prev-tab-view-id (:view-id db))
|
||||
(assoc :prev-view-id (:view-id db))
|
||||
(navigate-to-clean view-id))))
|
||||
(navigate-to-clean view-id))))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.ui.screens.profile.events
|
||||
(:require [clojure.spec.alpha :as spec]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame :refer [reg-fx]]
|
||||
[re-frame.core :as re-frame :refer [reg-fx trim-v]]
|
||||
[status-im.components.react :refer [show-image-picker]]
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
[status-im.ui.screens.profile.db :as db]
|
||||
|
@ -28,11 +28,13 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:profile/send-transaction
|
||||
(fn [_ [_ chat-id]]
|
||||
{:dispatch-n [[:clear-seq-arguments]
|
||||
[:navigate-to :chat chat-id]
|
||||
;; TODO https://github.com/status-im/status-react/issues/1621
|
||||
[:select-chat-input-command {:name "send"}]]}))
|
||||
[trim-v]
|
||||
(fn [{:keys [db]} [chat-id contact-id]]
|
||||
{:dispatch-n [[:navigate-to :chat chat-id]
|
||||
[:select-chat-input-command {:name "send"}]
|
||||
[:set-contact-as-command-argument {:arg-index 0
|
||||
:bot-db-key "recipient"
|
||||
:contact (get-in db [:contacts/contacts contact-id])}]]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:profile/send-message
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
[action-button {:label (label :t/send-transaction)
|
||||
:icon :icons/arrow-right
|
||||
:icon-opts {:color :blue}
|
||||
:on-press #(dispatch [:profile/send-transaction chat-id])}]])])
|
||||
:on-press #(dispatch [:profile/send-transaction chat-id whisper-identity])}]])])
|
||||
|
||||
(defn profile-info-item [{:keys [label value options text-mode empty-value? accessibility-label]}]
|
||||
[react/view styles/profile-setting-item
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
(ns status-im.utils.sms-listener
|
||||
(:require [status-im.utils.platform :refer [android?]]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.platform :refer [android?]]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]))
|
||||
|
||||
;; Only android is supported!
|
||||
(defn add-sms-listener
|
||||
"Message format: {:originatingAddress string, :body string}. Returns
|
||||
cancelable subscription."
|
||||
[listen-fn]
|
||||
[listen-event-creator]
|
||||
(when android?
|
||||
(.addListener rn-dependencies/android-sms-listener
|
||||
(fn [message]
|
||||
(listen-fn (js->clj message :keywordize-keys true))))))
|
||||
(re-frame/dispatch (listen-event-creator (js->clj message :keywordize-keys true)))))))
|
||||
|
||||
(defn remove-sms-listener [subscription]
|
||||
(when android?
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
(ns status-im.test.chat.events
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
reagent.core
|
||||
[re-frame.core :as rf]
|
||||
[day8.re-frame.test :refer [run-test-sync]]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.sign-up :as sign-up]
|
||||
[status-im.chat.events :as chat-events]))
|
||||
|
||||
(def contact
|
||||
{:address "c296367a939e0957500a25ca89b70bd64b03004e"
|
||||
:whisper-identity "0x04f5722fba79eb36d73263417531007f43d13af76c6233573a8e3e60f667710611feba0785d751b50609bfc0b7cef35448875c5392c0a91948c95798a0ce600847"
|
||||
:name "testuser"
|
||||
:photo-path "contacts://testuser"
|
||||
:dapp? false})
|
||||
|
||||
(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 sign-up/console-chat}}
|
||||
fx (chat-events/init-console-chat db false)]
|
||||
(is (= db (:db fx)))
|
||||
(is (= #{:db} (-> fx keys set)))))
|
||||
|
||||
(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 false)]
|
||||
(is (= (:current-chat-id db)
|
||||
(:chat-id sign-up/console-chat)))
|
||||
(is (= (:new-chat db)
|
||||
sign-up/console-chat))
|
||||
(is (= (:current-chat-id db)
|
||||
const/console-chat-id))
|
||||
(is (= dispatch-n
|
||||
(concat [[:add-contacts [sign-up/console-contact]]]
|
||||
sign-up/intro-events)))))
|
||||
|
||||
(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 false)]
|
||||
(is (= (:current-chat-id db)
|
||||
(:chat-id sign-up/console-chat)))
|
||||
(is (= (:new-chat db)
|
||||
sign-up/console-chat))
|
||||
(is (= (:current-chat-id db)
|
||||
const/console-chat-id))
|
||||
(is (= dispatch-n [[:add-contacts [sign-up/console-contact]]])))))
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.test.runner
|
||||
(:require [doo.runner :refer-macros [doo-tests]]
|
||||
[status-im.test.chat.events]
|
||||
[status-im.test.contacts.events]
|
||||
[status-im.test.accounts.events]
|
||||
[status-im.test.wallet.events]
|
||||
|
@ -24,17 +25,18 @@
|
|||
(set! goog.DEBUG false)
|
||||
|
||||
(doo-tests
|
||||
'status-im.test.accounts.events
|
||||
'status-im.test.contacts.events
|
||||
'status-im.test.profile.events
|
||||
'status-im.test.wallet.events
|
||||
'status-im.test.chat.models.input
|
||||
'status-im.test.components.main-tabs
|
||||
'status-im.test.handlers
|
||||
'status-im.test.utils.utils
|
||||
'status-im.test.utils.money
|
||||
'status-im.test.utils.clocks
|
||||
'status-im.test.utils.erc20
|
||||
'status-im.test.utils.random
|
||||
'status-im.test.utils.gfycat.core
|
||||
'status-im.test.utils.signing-phrase.core)
|
||||
'status-im.test.chat.events
|
||||
'status-im.test.accounts.events
|
||||
'status-im.test.contacts.events
|
||||
'status-im.test.profile.events
|
||||
'status-im.test.wallet.events
|
||||
'status-im.test.chat.models.input
|
||||
'status-im.test.components.main-tabs
|
||||
'status-im.test.handlers
|
||||
'status-im.test.utils.utils
|
||||
'status-im.test.utils.money
|
||||
'status-im.test.utils.clocks
|
||||
'status-im.test.utils.erc20
|
||||
'status-im.test.utils.random
|
||||
'status-im.test.utils.gfycat.core
|
||||
'status-im.test.utils.signing-phrase.core)
|
||||
|
|
Loading…
Reference in New Issue