mirror of
https://github.com/status-im/status-react.git
synced 2025-01-10 19:16:59 +00:00
refactored protocol handlers
This commit is contained in:
parent
a3c02b07a6
commit
afd7fca6d8
@ -624,7 +624,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sendWeb3Request(final String host, final String payload, final Callback callback) {
|
||||
public void sendWeb3Request(final String payload, final Callback callback) {
|
||||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -341,8 +341,7 @@ RCT_EXPORT_METHOD(clearStorageAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(sendWeb3Request:(NSString *)host
|
||||
password:(NSString *)payload
|
||||
RCT_EXPORT_METHOD(sendWeb3Request:(NSString *)payload
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
char * result = CallRPC((char *) [payload UTF8String]);
|
||||
|
@ -15,10 +15,10 @@
|
||||
(def adjust-pan 32)
|
||||
|
||||
#_(defn- wrap-and-print-callback [name callback]
|
||||
(fn [& args]
|
||||
(println :callback name (str args))
|
||||
(log/debug :callback name args)
|
||||
(apply callback args)))
|
||||
(fn [& args]
|
||||
(println :callback name (str args))
|
||||
(log/debug :callback name args)
|
||||
(apply callback args)))
|
||||
|
||||
(defn init-jail []
|
||||
(module-interface/-init-jail rns-module))
|
||||
@ -75,8 +75,8 @@
|
||||
(defn clear-web-data []
|
||||
(module-interface/-clear-web-data rns-module))
|
||||
|
||||
(defn call-web3 [host payload callback]
|
||||
(module-interface/-call-web3 rns-module host payload callback))
|
||||
(defn call-web3 [payload callback]
|
||||
(module-interface/-call-web3 rns-module payload callback))
|
||||
|
||||
(defn module-initialized! []
|
||||
(module-interface/-module-initialized! rns-module))
|
||||
|
@ -205,9 +205,9 @@
|
||||
(call-module #(.clearCookies status))
|
||||
(call-module #(.clearStorageAPIs status))))
|
||||
|
||||
(defn call-web3 [host payload callback]
|
||||
(defn call-web3 [payload callback]
|
||||
(when status
|
||||
(call-module #(.sendWeb3Request status host payload callback))))
|
||||
(call-module #(.sendWeb3Request status payload callback))))
|
||||
|
||||
(defn close-application []
|
||||
(.closeApplication status))
|
||||
@ -237,8 +237,8 @@
|
||||
(call-jail params))
|
||||
(-call-function! [this params]
|
||||
(call-function! params))
|
||||
(-call-web3 [this host payload callback]
|
||||
(call-web3 host payload callback))
|
||||
(-call-web3 [this payload callback]
|
||||
(call-web3 payload callback))
|
||||
(-notify [this token callback]
|
||||
(notify token callback))
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
"●●●●●●●●●●"]}}})
|
||||
:else (callback {:result nil})))
|
||||
(-call-function! [this params])
|
||||
(-call-web3 [this host payload callback])
|
||||
(-call-web3 [this payload callback])
|
||||
|
||||
;; other calls
|
||||
(-move-to-internal-storage [this callback]
|
||||
|
@ -15,7 +15,7 @@
|
||||
(-call-function! [this params])
|
||||
(-set-soft-input-mode [this mode])
|
||||
(-clear-web-data [this])
|
||||
(-call-web3 [this host payload callback])
|
||||
(-call-web3 [this payload callback])
|
||||
(-module-initialized! [this])
|
||||
(-should-move-to-internal-storage? [this callback])
|
||||
(-notify [this token callback])
|
||||
|
@ -1,146 +1,125 @@
|
||||
(ns status-im.protocol.handlers
|
||||
(:require [status-im.utils.handlers :as u]
|
||||
[re-frame.core :refer [dispatch after] :as re-frame]
|
||||
[status-im.utils.handlers :refer [register-handler]]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.data-store.pending-messages :as pending-messages]
|
||||
[status-im.data-store.processed-messages :as processed-messages]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.constants :refer [text-content-type
|
||||
blocks-per-hour]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.protocol.message-cache :as cache]
|
||||
[status-im.utils.datetime :as dt]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[taoensso.timbre :as log :refer-macros [debug]]
|
||||
[status-im.constants :as c]
|
||||
[status-im.native-module.core :as status]
|
||||
[clojure.string :refer [join]]
|
||||
[status-im.utils.scheduler :as s]
|
||||
[status-im.utils.web3-provider :as w3]
|
||||
[status-im.utils.datetime :as time]))
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.web3-provider :as web3-provider]))
|
||||
|
||||
;;;; COFX
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::get-web3
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :web3 (web3-provider/make-web3))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::get-chat-groups
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :groups (chats/get-active-group-chats))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::get-pending-messages
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :pending-messages (pending-messages/get-all))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::get-all-contacts
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :contacts (contacts/get-all))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::message-get-by-id
|
||||
(fn [coeffects _]
|
||||
(let [[{{:keys [message-id]} :payload}] (:event coeffects)]
|
||||
(assoc coeffects :message-by-id (messages/get-by-id message-id)))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::chats-new-update?
|
||||
(fn [coeffects _]
|
||||
(let [[{{:keys [group-id timestamp]} :payload}] (:event coeffects)]
|
||||
(assoc coeffects :new-update? (chats/new-update? timestamp group-id)))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::chats-is-active-and-timestamp
|
||||
(fn [coeffects _]
|
||||
(let [[{{:keys [group-id timestamp]} :payload}] (:event coeffects)]
|
||||
(assoc coeffects :chats-is-active-and-timestamp
|
||||
(and (chats/is-active? group-id)
|
||||
(> timestamp (chats/get-property group-id :timestamp)))))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::chats-is-active?
|
||||
(fn [coeffects _]
|
||||
(let [[{{:keys [group-id]} :payload from :from}] (:event coeffects)]
|
||||
(assoc coeffects :chats-is-active?
|
||||
(chats/is-active? (or group-id from))))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::has-contact?
|
||||
(fn [coeffects _]
|
||||
(let [[{{:keys [group-id identity]} :payload}] (:event coeffects)]
|
||||
(assoc coeffects :has-contact? (chats/has-contact? group-id identity)))))
|
||||
|
||||
|
||||
;;;; FX
|
||||
|
||||
(re-frame/reg-fx
|
||||
:stop-whisper
|
||||
(fn [] (protocol/stop-whisper!)))
|
||||
|
||||
(register-handler :initialize-protocol
|
||||
(fn [db [_ current-account-id ethereum-rpc-url]]
|
||||
(let [{:keys [public-key status updates-public-key
|
||||
updates-private-key]}
|
||||
(get-in db [:accounts/accounts current-account-id])]
|
||||
(if public-key
|
||||
(let [rpc-url (or ethereum-rpc-url c/ethereum-rpc-url)
|
||||
groups (chats/get-active-group-chats)
|
||||
web3 (w3/make-web3 rpc-url)]
|
||||
(protocol/init-whisper!
|
||||
{:web3 web3
|
||||
:identity public-key
|
||||
:groups groups
|
||||
:callback #(dispatch [:incoming-message %1 %2])
|
||||
:ack-not-received-s-interval 125
|
||||
:default-ttl 120
|
||||
:send-online-s-interval 180
|
||||
:ttl-config {:public-group-message 2400}
|
||||
:max-attempts-number 3
|
||||
:delivery-loop-ms-interval 500
|
||||
:profile-keypair {:public updates-public-key
|
||||
:private updates-private-key}
|
||||
:hashtags (u/get-hashtags status)
|
||||
:pending-messages (pending-messages/get-all)
|
||||
:contacts (keep (fn [{:keys [whisper-identity
|
||||
public-key
|
||||
private-key]}]
|
||||
(when (and public-key private-key)
|
||||
{:identity whisper-identity
|
||||
:keypair {:public public-key
|
||||
:private private-key}}))
|
||||
(contacts/get-all))
|
||||
:post-error-callback #(dispatch [::post-error %])})
|
||||
(assoc db :web3 web3
|
||||
:rpc-url rpc-url))
|
||||
db))))
|
||||
(re-frame/reg-fx
|
||||
::init-whisper
|
||||
(fn [{:keys [web3 public-key groups updates-public-key updates-private-key status contacts pending-messages]}]
|
||||
(protocol/init-whisper!
|
||||
{:web3 web3
|
||||
:identity public-key
|
||||
:groups groups
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])
|
||||
:ack-not-received-s-interval 125
|
||||
:default-ttl 120
|
||||
:send-online-s-interval 180
|
||||
:ttl-config {:public-group-message 2400}
|
||||
:max-attempts-number 3
|
||||
:delivery-loop-ms-interval 500
|
||||
:profile-keypair {:public updates-public-key
|
||||
:private updates-private-key}
|
||||
:hashtags (handlers/get-hashtags status)
|
||||
:pending-messages pending-messages
|
||||
:contacts (keep (fn [{:keys [whisper-identity
|
||||
public-key
|
||||
private-key]}]
|
||||
(when (and public-key private-key)
|
||||
{:identity whisper-identity
|
||||
:keypair {:public public-key
|
||||
:private private-key}}))
|
||||
contacts)
|
||||
:post-error-callback #(re-frame/dispatch [::post-error %])})))
|
||||
|
||||
(register-handler :update-sync-state
|
||||
(u/side-effect!
|
||||
(fn [{:keys [sync-state sync-data]} [_ error sync]]
|
||||
(let [{:keys [highestBlock currentBlock] :as state}
|
||||
(js->clj sync :keywordize-keys true)
|
||||
syncing? (> (- highestBlock currentBlock) blocks-per-hour)
|
||||
new-state (cond
|
||||
error :offline
|
||||
syncing? (if (= sync-state :done)
|
||||
:pending
|
||||
:in-progress)
|
||||
:else (if (or (= sync-state :done)
|
||||
(= sync-state :pending))
|
||||
:done
|
||||
:synced))]
|
||||
(when (and (not= sync-data state) (= :in-progress new-state))
|
||||
(dispatch [:set :sync-data state]))
|
||||
(when (not= sync-state new-state)
|
||||
(dispatch [:set :sync-state new-state]))))))
|
||||
(re-frame/reg-fx
|
||||
::web3-get-syncing
|
||||
(fn [web3]
|
||||
(when web3
|
||||
(.getSyncing
|
||||
(.-eth web3)
|
||||
(fn [error sync]
|
||||
(re-frame/dispatch [:update-sync-state error sync]))))))
|
||||
|
||||
(register-handler :check-sync
|
||||
(u/side-effect!
|
||||
(fn [{:keys [web3] :as db}]
|
||||
(if web3
|
||||
(do (.getSyncing
|
||||
(.-eth web3)
|
||||
(fn [error sync]
|
||||
(dispatch [:update-sync-state error sync])))
|
||||
(s/execute-later #(dispatch [:check-sync]) (s/s->ms 10)))
|
||||
(s/execute-later #(dispatch [:check-sync]) (s/s->ms 10))))))
|
||||
|
||||
(register-handler :initialize-sync-listener
|
||||
(fn [{:keys [sync-listening-started] :as db} _]
|
||||
(if-not sync-listening-started
|
||||
(do
|
||||
(dispatch [:check-sync])
|
||||
(assoc db :sync-listening-started true))
|
||||
db)))
|
||||
|
||||
(register-handler :incoming-message
|
||||
(u/side-effect!
|
||||
(fn [_ [_ type {:keys [payload ttl id] :as message}]]
|
||||
(let [message-id (or id (:message-id payload))]
|
||||
(when-not (cache/exists? message-id type)
|
||||
(let [ttl-s (* 1000 (or ttl 120))
|
||||
processed-message {:id (random/id)
|
||||
:message-id message-id
|
||||
:type type
|
||||
:ttl (+ (dt/now-ms) ttl-s)}]
|
||||
(cache/add! processed-message)
|
||||
(processed-messages/save processed-message))
|
||||
(case type
|
||||
:message (dispatch [:received-protocol-message! message])
|
||||
:group-message (dispatch [:received-protocol-message! message])
|
||||
:public-group-message (dispatch [:received-protocol-message! message])
|
||||
:ack (if (#{:message :group-message} (:type payload))
|
||||
(dispatch [:message-delivered message])
|
||||
(dispatch [:pending-message-remove message]))
|
||||
:seen (dispatch [:message-seen message])
|
||||
:group-invitation (dispatch [:group-chat-invite-received message])
|
||||
:update-group (dispatch [:update-group-message message])
|
||||
:add-group-identity (dispatch [:participant-invited-to-group message])
|
||||
:remove-group-identity (dispatch [:participant-removed-from-group message])
|
||||
:leave-group (dispatch [:participant-left-group message])
|
||||
:contact-request (dispatch [:contact-request-received message])
|
||||
:discover (dispatch [:status-received message])
|
||||
:discoveries-request (dispatch [:discoveries-request-received message])
|
||||
:discoveries-response (dispatch [:discoveries-response-received message])
|
||||
:profile (dispatch [:contact-update-received message])
|
||||
:update-keys (dispatch [:update-keys-received message])
|
||||
:online (dispatch [:contact-online-received message])
|
||||
:pending (dispatch [:pending-message-upsert message])
|
||||
:sent (let [{:keys [to id group-id]} message
|
||||
message' {:from to
|
||||
:payload {:message-id id
|
||||
:group-id group-id}}]
|
||||
(dispatch [:message-sent message']))
|
||||
(debug "Unknown message type" type)))))))
|
||||
(re-frame/reg-fx
|
||||
::save-processed-messages
|
||||
(fn [processed-message]
|
||||
(processed-messages/save processed-message)))
|
||||
|
||||
(defn system-message
|
||||
([message-id timestamp content]
|
||||
@ -148,144 +127,78 @@
|
||||
:message-id message-id
|
||||
:timestamp timestamp
|
||||
:content content
|
||||
:content-type text-content-type}))
|
||||
:content-type constants/text-content-type}))
|
||||
|
||||
(defn joined-chat-message [chat-id from message-id]
|
||||
(let [contact-name (:name (contacts/get-by-id from))]
|
||||
(messages/save chat-id {:from "system"
|
||||
:message-id (str message-id "_" from)
|
||||
:content (str (or contact-name from) " " (label :t/received-invitation))
|
||||
:content-type text-content-type})))
|
||||
(re-frame/reg-fx
|
||||
::participant-removed-from-group-message
|
||||
(fn [{:keys [identity from message-id timestamp group-id]}]
|
||||
(let [remover-name (:name (contacts/get-by-id from))
|
||||
removed-name (:name (contacts/get-by-id identity))
|
||||
message (->> [(or remover-name from) (i18n/label :t/removed) (or removed-name identity)]
|
||||
(string/join " ")
|
||||
(system-message message-id timestamp))
|
||||
message' (assoc message :group-id group-id)]
|
||||
(re-frame/dispatch [:received-message message']))))
|
||||
|
||||
(defn participant-invited-to-group-message [chat-id current-identity identity from message-id timestamp]
|
||||
(let [inviter-name (:name (contacts/get-by-id from))
|
||||
invitee-name (if (= identity current-identity)
|
||||
(label :t/You)
|
||||
(:name (contacts/get-by-id identity)))]
|
||||
{:from "system"
|
||||
:group-id chat-id
|
||||
:timestamp timestamp
|
||||
:message-id message-id
|
||||
:content (str (or inviter-name from) " " (label :t/invited) " " (or invitee-name identity))
|
||||
:content-type text-content-type}))
|
||||
(re-frame/reg-fx
|
||||
::chats-add-contact
|
||||
(fn [[group-id identity]]
|
||||
(chats/add-contacts group-id [identity])))
|
||||
|
||||
(defn participant-removed-from-group-message
|
||||
[identity from {:keys [message-id timestamp]}]
|
||||
(let [remover-name (:name (contacts/get-by-id from))
|
||||
removed-name (:name (contacts/get-by-id identity))]
|
||||
(->> [(or remover-name from) (label :t/removed) (or removed-name identity)]
|
||||
(join " ")
|
||||
(system-message message-id timestamp))))
|
||||
(re-frame/reg-fx
|
||||
::chats-remove-contact
|
||||
(fn [[group-id identity]]
|
||||
(chats/remove-contacts group-id [identity])))
|
||||
|
||||
(defn you-removed-from-group-message
|
||||
[from {:keys [message-id timestamp]}]
|
||||
(let [remover-name (:name (contacts/get-by-id from))]
|
||||
(->> [(or remover-name from) (label :t/removed-from-chat)]
|
||||
(join " ")
|
||||
(->> [(or remover-name from) (i18n/label :t/removed-from-chat)]
|
||||
(string/join " ")
|
||||
(system-message message-id timestamp))))
|
||||
|
||||
(defn participant-left-group-message
|
||||
[chat-id from {:keys [message-id timestamp]}]
|
||||
(let [left-name (:name (contacts/get-by-id from))]
|
||||
(->> (str (or left-name from) " " (label :t/left))
|
||||
(system-message message-id timestamp)
|
||||
(messages/save chat-id))))
|
||||
(re-frame/reg-fx
|
||||
::you-removed-from-group-message
|
||||
(fn [{:keys [from message-id timestamp group-id]}]
|
||||
(let [remover-name (:name (contacts/get-by-id from))
|
||||
message (->> [(or remover-name from) (i18n/label :t/removed-from-chat)]
|
||||
(string/join " ")
|
||||
(system-message message-id timestamp))
|
||||
message' (assoc message :group-id group-id)]
|
||||
(re-frame/dispatch [:received-message message']))))
|
||||
|
||||
(register-handler :group-chat-invite-acked
|
||||
(u/side-effect!
|
||||
(fn [_ [action from group-id ack-message-id]]
|
||||
(log/debug action from group-id ack-message-id)
|
||||
#_(joined-chat-message group-id from ack-message-id))))
|
||||
(re-frame/reg-fx
|
||||
::stop-watching-group!
|
||||
(fn [params]
|
||||
(protocol/stop-watching-group! params)))
|
||||
|
||||
(register-handler :participant-removed-from-group
|
||||
(u/side-effect!
|
||||
(fn [{:keys [current-public-key chats]}
|
||||
[_ {:keys [from]
|
||||
{:keys [group-id identity message-id] :as payload} :payload
|
||||
:as message}]]
|
||||
(when-not (messages/get-by-id message-id)
|
||||
(let [admin (get-in chats [group-id :group-admin])]
|
||||
(when (= admin from)
|
||||
(if (= current-public-key identity)
|
||||
(dispatch [::you-removed-from-group message])
|
||||
(let [message
|
||||
(assoc
|
||||
(participant-removed-from-group-message identity from payload)
|
||||
:group-id group-id)]
|
||||
(chats/remove-contacts group-id [identity])
|
||||
(dispatch [:received-message message])))))))))
|
||||
(re-frame/reg-fx
|
||||
::participant-left-group-message
|
||||
(fn [{:keys [chat-id from message-id timestamp]}]
|
||||
(let [left-name (:name (contacts/get-by-id from))]
|
||||
(->> (str (or left-name from) " " (i18n/label :t/left))
|
||||
(system-message message-id timestamp)
|
||||
(messages/save chat-id)))))
|
||||
|
||||
(register-handler ::you-removed-from-group
|
||||
(u/side-effect!
|
||||
(fn [{:keys [web3]}
|
||||
[_ {:keys [from]
|
||||
{:keys [group-id timestamp] :as payload} :payload}]]
|
||||
(when (chats/new-update? timestamp group-id)
|
||||
(let [message (you-removed-from-group-message from payload)
|
||||
message' (assoc message :group-id group-id)]
|
||||
(dispatch [:received-message message']))
|
||||
(protocol/stop-watching-group! {:web3 web3
|
||||
:group-id group-id})
|
||||
(dispatch [:update-chat! {:chat-id group-id
|
||||
:removed-from-at timestamp
|
||||
:is-active false}])))))
|
||||
(re-frame/reg-fx
|
||||
::participant-invited-to-group-message
|
||||
(fn [{:keys [chat-id current-identity identity from message-id timestamp]}]
|
||||
(let [inviter-name (:name (contacts/get-by-id from))
|
||||
invitee-name (if (= identity current-identity)
|
||||
(i18n/label :t/You)
|
||||
(:name (contacts/get-by-id identity)))]
|
||||
(re-frame/dispatch
|
||||
[:received-message
|
||||
{:from "system"
|
||||
:group-id chat-id
|
||||
:timestamp timestamp
|
||||
:message-id message-id
|
||||
:content (str (or inviter-name from) " " (i18n/label :t/invited) " " (or invitee-name identity))
|
||||
:content-type constants/text-content-type}]))))
|
||||
|
||||
(register-handler :participant-left-group
|
||||
(u/side-effect!
|
||||
(fn [{:keys [current-public-key]}
|
||||
[_ {:keys [from]
|
||||
{:keys [group-id timestamp] :as payload} :payload}]]
|
||||
(when (and (not= current-public-key from)
|
||||
(chats/is-active? group-id)
|
||||
(> timestamp (chats/get-property group-id :timestamp)))
|
||||
(participant-left-group-message group-id from payload)
|
||||
(dispatch [::remove-identity-from-chat group-id from])
|
||||
(dispatch [::remove-identity-from-chat! group-id from])))))
|
||||
|
||||
(register-handler ::remove-identity-from-chat
|
||||
(fn [db [_ chat-id id]]
|
||||
(update-in db [:chats chat-id :contacts]
|
||||
#(remove (fn [{:keys [identity]}]
|
||||
(= identity id)) %))))
|
||||
|
||||
(register-handler ::remove-identity-from-chat!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ group-id identity]]
|
||||
(chats/remove-contacts group-id [identity]))))
|
||||
|
||||
(register-handler :participant-invited-to-group
|
||||
(u/side-effect!
|
||||
(fn [{:keys [current-public-key chats]}
|
||||
[_ {:keys [from]
|
||||
{:keys [group-id identity message-id timestamp]} :payload}]]
|
||||
(let [admin (get-in chats [group-id :group-admin])]
|
||||
(when (= from admin)
|
||||
(dispatch
|
||||
[:received-message
|
||||
(participant-invited-to-group-message group-id current-public-key identity from message-id timestamp)])
|
||||
(when-not (= current-public-key identity)
|
||||
(dispatch [:add-contact-to-group! group-id identity])))))))
|
||||
|
||||
(register-handler :add-contact-to-group!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ group-id identity]]
|
||||
(when-not (chats/has-contact? group-id identity)
|
||||
(dispatch [::add-contact group-id identity])
|
||||
(dispatch [::store-contact! group-id identity])))))
|
||||
|
||||
(register-handler ::add-contact
|
||||
(fn [db [_ group-id identity]]
|
||||
(update-in db [:chats group-id :contacts] conj {:identity identity})))
|
||||
|
||||
(register-handler ::store-contact!
|
||||
(u/side-effect!
|
||||
(fn [_ [_ group-id identity]]
|
||||
(chats/add-contacts group-id [identity]))))
|
||||
|
||||
(defn save-message-status! [status]
|
||||
(fn [_ [_
|
||||
{:keys [from]
|
||||
{:keys [message-id ack-of-message group-id]} :payload}]]
|
||||
(re-frame/reg-fx
|
||||
::save-message-status!
|
||||
(fn [{:keys [message-id ack-of-message group-id from status]}]
|
||||
(let [message-id' (or ack-of-message message-id)]
|
||||
(when-let [{:keys [message-status] :as message} (messages/get-by-id message-id')]
|
||||
(when-not (= (keyword message-status) :seen)
|
||||
@ -304,107 +217,290 @@
|
||||
(dissoc :preview))]
|
||||
(messages/update-message message')))))))
|
||||
|
||||
(defn update-message-status [status]
|
||||
(fn [db
|
||||
[_ {:keys [from]
|
||||
{:keys [message-id ack-of-message group-id]} :payload}]]
|
||||
(if (chats/is-active? (or group-id from))
|
||||
(let [message-id' (or ack-of-message message-id)
|
||||
group? (boolean group-id)
|
||||
status-path (if (and group? (not= status :sent))
|
||||
[:message-data :user-statuses message-id' from]
|
||||
[:message-data :statuses message-id'])
|
||||
{current-status :status} (get-in db status-path)]
|
||||
(if-not (= :seen current-status)
|
||||
(assoc-in db status-path {:whisper-identity from
|
||||
:status status})
|
||||
db))
|
||||
db)))
|
||||
(re-frame/reg-fx
|
||||
::pending-messages-delete
|
||||
(fn [message]
|
||||
(pending-messages/delete message)))
|
||||
|
||||
(defn remove-pending-message
|
||||
[_ [_ message]]
|
||||
(dispatch [:pending-message-remove message]))
|
||||
(re-frame/reg-fx
|
||||
::pending-messages-save
|
||||
(fn [{:keys [type id pending-message]}]
|
||||
(pending-messages/save pending-message)
|
||||
(when (#{:message :group-message} type)
|
||||
(messages/update-message {:message-id id
|
||||
:delivery-status :pending}))))
|
||||
|
||||
(register-handler :message-delivered
|
||||
[(after (save-message-status! :delivered))
|
||||
(after remove-pending-message)]
|
||||
(update-message-status :delivered))
|
||||
(re-frame/reg-fx
|
||||
::status-init-jail
|
||||
(fn []
|
||||
(status/init-jail)))
|
||||
|
||||
(register-handler :message-failed
|
||||
(after (save-message-status! :failed))
|
||||
(update-message-status :failed))
|
||||
(re-frame/reg-fx
|
||||
::load-processed-messages!
|
||||
(fn []
|
||||
(let [now (datetime/now-ms)
|
||||
messages (processed-messages/get-filtered (str "ttl > " now))]
|
||||
(cache/init! messages)
|
||||
(processed-messages/delete (str "ttl <=" now)))))
|
||||
|
||||
(register-handler :message-sent
|
||||
(after (save-message-status! :sent))
|
||||
(update-message-status :sent))
|
||||
|
||||
(register-handler :message-seen
|
||||
[(after (save-message-status! :seen))]
|
||||
(update-message-status :seen))
|
||||
;;;; Handlers
|
||||
|
||||
(register-handler :pending-message-upsert
|
||||
(after
|
||||
(fn [_ [_ {:keys [type id] :as pending-message}]]
|
||||
(pending-messages/save pending-message)
|
||||
(when (#{:message :group-message} type)
|
||||
(messages/update-message {:message-id id
|
||||
:delivery-status :pending}))))
|
||||
(fn [db [_ {:keys [type id to group-id]}]]
|
||||
(if (#{:message :group-message} type)
|
||||
(let [chat-id (or group-id to)
|
||||
current-status (get-in db [:message-status chat-id id])]
|
||||
(if-not (= :seen current-status)
|
||||
(assoc-in db [:message-status chat-id id] :pending)
|
||||
db))
|
||||
db)))
|
||||
|
||||
(register-handler :pending-message-remove
|
||||
(u/side-effect!
|
||||
(fn [_ [_ message]]
|
||||
(pending-messages/delete message))))
|
||||
;;; INITIALIZE PROTOCOL
|
||||
(handlers/register-handler-fx
|
||||
:initialize-protocol
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::get-web3)
|
||||
(re-frame/inject-cofx ::get-chat-groups)
|
||||
(re-frame/inject-cofx ::get-pending-messages)
|
||||
(re-frame/inject-cofx ::get-all-contacts)]
|
||||
(fn [{:keys [db web3 groups contacts pending-messages]} [current-account-id ethereum-rpc-url]]
|
||||
(let [{:keys [public-key status updates-public-key
|
||||
updates-private-key]}
|
||||
(get-in db [:accounts/accounts current-account-id])]
|
||||
(when public-key
|
||||
{::init-whisper {:web3 web3 :public-key public-key :groups groups :pending-messages pending-messages
|
||||
:updates-public-key updates-public-key :updates-private-key updates-private-key
|
||||
:status status :contacts contacts}
|
||||
:db (assoc db :web3 web3
|
||||
:rpc-url (or ethereum-rpc-url constants/ethereum-rpc-url))}))))
|
||||
|
||||
(register-handler :contact-request-received
|
||||
(u/side-effect!
|
||||
(fn [{:contacts/keys [contacts]} [_ {:keys [from payload]}]]
|
||||
(when from
|
||||
(let [{{:keys [name profile-image address status fcm-token]} :contact
|
||||
{:keys [public private]} :keypair} payload
|
||||
existing-contact (get contacts from)
|
||||
contact {:whisper-identity from
|
||||
:public-key public
|
||||
:private-key private
|
||||
:address address
|
||||
:status status
|
||||
:photo-path profile-image
|
||||
:name name
|
||||
:fcm-token fcm-token}
|
||||
chat {:name name
|
||||
:chat-id from
|
||||
:contact-info (prn-str contact)}]
|
||||
(if-not existing-contact
|
||||
(let [contact (assoc contact :pending? true)]
|
||||
(dispatch [:add-contacts [contact]])
|
||||
(dispatch [:add-chat from chat]))
|
||||
(when-not (:pending? existing-contact)
|
||||
(dispatch [:update-contact! contact])
|
||||
(dispatch [:update-chat! chat])
|
||||
(dispatch [:watch-contact contact]))))))))
|
||||
|
||||
(register-handler ::post-error
|
||||
(u/side-effect!
|
||||
(fn [_ [_ error]]
|
||||
(.log js/console error)
|
||||
(let [message (.-message error)
|
||||
ios-error? (re-find (re-pattern "Could not connect to the server.") message)
|
||||
android-error? (re-find (re-pattern "Failed to connect") message)]
|
||||
(when (or ios-error? android-error?)
|
||||
(when android-error? (status/init-jail)))))))
|
||||
|
||||
(register-handler
|
||||
(handlers/register-handler-fx
|
||||
:load-processed-messages
|
||||
(u/side-effect!
|
||||
(fn [_]
|
||||
(let [now (time/now-ms)
|
||||
messages (processed-messages/get-filtered (str "ttl > " now))]
|
||||
(cache/init! messages)
|
||||
(processed-messages/delete (str "ttl <=" now))))))
|
||||
(fn [_ _]
|
||||
{::load-processed-messages! nil}))
|
||||
|
||||
;;; NODE SYNC STATE
|
||||
|
||||
(handlers/register-handler-db
|
||||
:update-sync-state
|
||||
(fn [{:keys [sync-state sync-data] :as db} [_ error sync]]
|
||||
(let [{:keys [highestBlock currentBlock] :as state}
|
||||
(js->clj sync :keywordize-keys true)
|
||||
syncing? (> (- highestBlock currentBlock) constants/blocks-per-hour)
|
||||
new-state (cond
|
||||
error :offline
|
||||
syncing? (if (= sync-state :done)
|
||||
:pending
|
||||
:in-progress)
|
||||
:else (if (or (= sync-state :done)
|
||||
(= sync-state :pending))
|
||||
:done
|
||||
:synced))]
|
||||
(cond-> db
|
||||
(when (and (not= sync-data state) (= :in-progress new-state)))
|
||||
(assoc :sync-data state)
|
||||
(when (not= sync-state new-state))
|
||||
(assoc :sync-state new-state)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:check-sync
|
||||
(fn [{{:keys [web3] :as db} :db} _]
|
||||
{::web3-get-syncing web3
|
||||
:dispatch-later [{:ms 10000 :dispatch [:check-sync]}]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:initialize-sync-listener
|
||||
(fn [{{:keys [sync-listening-started] :as db} :db} _]
|
||||
(when-not sync-listening-started
|
||||
{:db (assoc db :sync-listening-started true)
|
||||
:dispatch [:check-sync]})))
|
||||
|
||||
;;; MESSAGES
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:incoming-message
|
||||
(fn [_ [_ type {:keys [payload ttl id] :as message}]]
|
||||
(let [message-id (or id (:message-id payload))]
|
||||
(when-not (cache/exists? message-id type)
|
||||
(let [ttl-s (* 1000 (or ttl 120))
|
||||
processed-message {:id (random/id)
|
||||
:message-id message-id
|
||||
:type type
|
||||
:ttl (+ (datetime/now-ms) ttl-s)}
|
||||
route-event (case type
|
||||
:message [:received-protocol-message! message]
|
||||
:group-message [:received-protocol-message! message]
|
||||
:public-group-message [:received-protocol-message! message]
|
||||
:ack (if (#{:message :group-message} (:type payload))
|
||||
[:update-message-status message :delivered]
|
||||
[:pending-message-remove message])
|
||||
:seen [:update-message-status message :seen]
|
||||
:group-invitation [:group-chat-invite-received message]
|
||||
:update-group [:update-group-message message]
|
||||
:add-group-identity [:participant-invited-to-group message]
|
||||
:remove-group-identity [:participant-removed-from-group message]
|
||||
:leave-group [:participant-left-group message]
|
||||
:contact-request [:contact-request-received message]
|
||||
:discover [:status-received message]
|
||||
:discoveries-request [:discoveries-request-received message]
|
||||
:discoveries-response [:discoveries-response-received message]
|
||||
:profile [:contact-update-received message]
|
||||
:update-keys [:update-keys-received message]
|
||||
:online [:contact-online-received message]
|
||||
:pending [:pending-message-upsert message]
|
||||
:sent (let [{:keys [to id group-id]} message
|
||||
message' {:from to
|
||||
:payload {:message-id id
|
||||
:group-id group-id}}]
|
||||
[:update-message-status message' :sent])
|
||||
nil)]
|
||||
(when (nil? route-event) (debug "Unknown message type" type))
|
||||
(cache/add! processed-message)
|
||||
(merge
|
||||
{::save-processed-messages processed-message}
|
||||
(when route-event {:dispatch route-event})))))))
|
||||
|
||||
(defn update-message-status [db {:keys [message-id ack-of-message group-id from status]}]
|
||||
(let [message-id' (or ack-of-message message-id)
|
||||
group? (boolean group-id)
|
||||
status-path (if (and group? (not= status :sent))
|
||||
[:message-data :user-statuses message-id' from]
|
||||
[:message-data :statuses message-id'])
|
||||
{current-status :status} (get-in db status-path)]
|
||||
(if-not (= :seen current-status)
|
||||
(assoc-in db status-path {:whisper-identity from
|
||||
:status status})
|
||||
db)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:update-message-status
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::chats-is-active?)]
|
||||
(fn [{db :db chats-is-active? :chats-is-active?}
|
||||
[{:keys [from]
|
||||
{:keys [message-id ack-of-message group-id]} :payload
|
||||
:as message}
|
||||
status]]
|
||||
(let [data {:status status
|
||||
:message-id message-id :ack-of-message ack-of-message
|
||||
:group-id group-id :from from}]
|
||||
(merge
|
||||
{::save-message-status! data}
|
||||
(when (= status :delivered)
|
||||
{:dispatch [:pending-message-remove message]})
|
||||
(when chats-is-active?
|
||||
{:db (update-message-status db data)})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact-request-received
|
||||
(fn [{{:contacts/keys [contacts]} :db}
|
||||
[_ {:keys [from payload]}]]
|
||||
(when from
|
||||
(let [{{:keys [name profile-image address status fcm-token]} :contact
|
||||
{:keys [public private]} :keypair} payload
|
||||
existing-contact (get contacts from)
|
||||
contact {:whisper-identity from
|
||||
:public-key public
|
||||
:private-key private
|
||||
:address address
|
||||
:status status
|
||||
:photo-path profile-image
|
||||
:name name
|
||||
:fcm-token fcm-token}
|
||||
chat {:name name
|
||||
:chat-id from
|
||||
:contact-info (prn-str contact)}]
|
||||
(if-not existing-contact
|
||||
(let [contact (assoc contact :pending? true)]
|
||||
{:dispatch-n [[:add-contacts [contact]]
|
||||
[:add-chat from chat]]})
|
||||
(when-not (:pending? existing-contact)
|
||||
{:dispatch-n [[:update-contact! contact]
|
||||
[:update-chat! chat]
|
||||
[:watch-contact contact]]}))))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:pending-message-upsert
|
||||
(fn [{db :db} [_ {:keys [type id to group-id] :as pending-message}]]
|
||||
(let [chat-id (or group-id to)
|
||||
current-status (get-in db [:message-status chat-id id])]
|
||||
(merge
|
||||
{::pending-messages-save {:type type :id id :pending-message pending-message}}
|
||||
(when (and (#{:message :group-message} type) (not= :seen current-status))
|
||||
{:db (assoc-in db [:message-status chat-id id] :pending)})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:pending-message-remove
|
||||
(fn [_ [_ message]]
|
||||
{::pending-messages-delete message}))
|
||||
|
||||
|
||||
|
||||
;;GROUP
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:participant-invited-to-group
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::has-contact?)]
|
||||
(fn [{{:keys [current-public-key chats] :as db} :db has-contact? :has-contact?}
|
||||
[{:keys [from]
|
||||
{:keys [group-id identity message-id timestamp]} :payload}]]
|
||||
(let [admin (get-in chats [group-id :group-admin])]
|
||||
(when (= from admin)
|
||||
(merge
|
||||
{::participant-invited-to-group-message {:group-id group-id :current-public-key current-public-key
|
||||
:identity identity :from from :message-id message-id
|
||||
:timestamp timestamp}}
|
||||
(when-not (and (= current-public-key identity) has-contact?)
|
||||
{:db (update-in db [:chats group-id :contacts] conj {:identity identity})
|
||||
::chats-add-contact [group-id [identity]]}))))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::you-removed-from-group
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::chats-new-update?)]
|
||||
(fn [{{:keys [web3]} :db new-update? :new-update?}
|
||||
[{:keys [from]
|
||||
{:keys [group-id timestamp message-id] :as payload} :payload}]]
|
||||
(when new-update?
|
||||
{::you-removed-from-group-message {:from from :message-id message-id :timestamp timestamp
|
||||
:group-id group-id}
|
||||
::stop-watching-group! {:web3 web3
|
||||
:group-id group-id}
|
||||
:dispatch [:update-chat! {:chat-id group-id
|
||||
:removed-from-at timestamp
|
||||
:is-active false}]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:participant-removed-from-group
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::message-get-by-id)]
|
||||
(fn [{{:keys [current-public-key chats]} :db message-by-id :message-by-id}
|
||||
[{:keys [from]
|
||||
{:keys [group-id identity message-id timestamp]} :payload
|
||||
:as message}]]
|
||||
(when-not message-by-id
|
||||
(let [admin (get-in chats [group-id :group-admin])]
|
||||
(when (= admin from)
|
||||
(if (= current-public-key identity)
|
||||
{:dispatch [::you-removed-from-group message]}
|
||||
{::participant-removed-from-group-message {:identity identity :from from :message-id message-id
|
||||
:timestamp timestamp :group-id group-id}
|
||||
::chats-remove-contact [group-id identity]}))))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:participant-left-group
|
||||
[re-frame/trim-v
|
||||
(re-frame/inject-cofx ::chats-is-active-and-timestamp)]
|
||||
(fn [{{:keys [current-public-key] :as db} :db chats-is-active-and-timestamp :chats-is-active-and-timestamp}
|
||||
[{:keys [from]
|
||||
{:keys [group-id timestamp message-id]} :payload}]]
|
||||
(when (and (not= current-public-key from)
|
||||
chats-is-active-and-timestamp)
|
||||
{::participant-left-group-message {:group-id group-id :from from :message-id message-id
|
||||
:timestamp timestamp}
|
||||
::chats-remove-contact [group-id from]
|
||||
:db (update-in db [:chats group-id :contacts]
|
||||
#(remove (fn [{:keys [identity]}]
|
||||
(= identity from)) %))})))
|
||||
|
||||
;;ERROR
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::post-error
|
||||
(fn [_ [_ error]]
|
||||
(let [android-error? (re-find (re-pattern "Failed to connect") (.-message error))]
|
||||
(when android-error?
|
||||
{::status-init-jail nil}))))
|
@ -3,17 +3,12 @@
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.js-dependencies :as dependencies]))
|
||||
|
||||
(defn get-provider [rpc-url]
|
||||
#js {:sendAsync (fn [payload callback]
|
||||
(status/call-web3
|
||||
rpc-url
|
||||
(.stringify js/JSON payload)
|
||||
(fn [response]
|
||||
(if (= "" response)
|
||||
(log/warn :web3-response-error)
|
||||
(callback nil (.parse js/JSON response))))))})
|
||||
|
||||
(defn make-web3 [rpc-url]
|
||||
(->> rpc-url
|
||||
get-provider
|
||||
dependencies/Web3.))
|
||||
(defn make-web3 []
|
||||
(dependencies/Web3.
|
||||
#js {:sendAsync (fn [payload callback]
|
||||
(status/call-web3
|
||||
(.stringify js/JSON payload)
|
||||
(fn [response]
|
||||
(if (= "" response)
|
||||
(log/warn :web3-response-error)
|
||||
(callback nil (.parse js/JSON response))))))}))
|
||||
|
Loading…
x
Reference in New Issue
Block a user