[fix 4177] handle discovery signals

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Eric Dvorsak 2018-05-18 02:30:33 +02:00 committed by Julien Eluard
parent b8e41cb464
commit 50072ffe3f
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
16 changed files with 310 additions and 219 deletions

View File

@ -10,8 +10,7 @@
com.andrewmcveigh/cljs-time {:mvn/version "0.5.2"} com.andrewmcveigh/cljs-time {:mvn/version "0.5.2"}
com.taoensso/timbre {:mvn/version "4.10.0"} com.taoensso/timbre {:mvn/version "4.10.0"}
hickory {:mvn/version "0.7.1"} hickory {:mvn/version "0.7.1"}
com.cognitect/transit-cljs {:mvn/version "0.8.248"} com.cognitect/transit-cljs {:mvn/version "0.8.248"}}
day8.re-frame/async-flow-fx {:mvn/version "0.0.10"}}
:aliases :aliases
{:repl {:extra-deps {:repl {:extra-deps

View File

@ -10,8 +10,7 @@
[com.andrewmcveigh/cljs-time "0.5.2"] [com.andrewmcveigh/cljs-time "0.5.2"]
[com.taoensso/timbre "4.10.0"] [com.taoensso/timbre "4.10.0"]
[hickory "0.7.1"] [hickory "0.7.1"]
[com.cognitect/transit-cljs "0.8.248"] [com.cognitect/transit-cljs "0.8.248"]]
[day8.re-frame/async-flow-fx "0.0.10"]]
:plugins [[lein-cljsbuild "1.1.7"] :plugins [[lein-cljsbuild "1.1.7"]
[lein-re-frisk "0.5.8"] [lein-re-frisk "0.5.8"]
[lein-cljfmt "0.5.7"] [lein-cljfmt "0.5.7"]

View File

@ -29,14 +29,11 @@
::update-connection-status ::update-connection-status
[re-frame/trim-v] [re-frame/trim-v]
(fn [{{:keys [network-status mailserver-status] :as db} :db :as cofx} [is-connected?]] (fn [{{:keys [network-status mailserver-status] :as db} :db :as cofx} [is-connected?]]
(let [should-recover? (and (= network-status :offline) (cond-> (handlers-macro/merge-fx cofx
is-connected? {:db (assoc db :network-status (if is-connected? :online :offline))}
(not= mailserver-status :connecting))] (inbox/request-messages {:discover? true}))
(cond-> (handlers-macro/merge-fx cofx is-connected?
{:db (assoc db :network-status (if is-connected? :online :offline))} (assoc :drain-mixpanel-events nil))))
(inbox/recover-offline-inbox should-recover?))
is-connected?
(assoc :drain-mixpanel-events nil)))))
(handlers/register-handler-fx (handlers/register-handler-fx
::update-network-status ::update-network-status

View File

@ -7,8 +7,10 @@
:chat-name "Chat name" :chat-name "Chat name"
:notifications-title "Notifications and sounds" :notifications-title "Notifications and sounds"
:offline "Offline" :offline "Offline"
:disconnected "Connecting to peers..."
:connection-problem "Messages connection problem" :connection-problem "Messages connection problem"
:mailserver-reconnect "Could not connect to mailserver. Tap to reconnect" :mailserver-reconnect "Could not connect to mailserver. Tap to reconnect"
:fetching-messages "Fetching messages..."
:search-for "Search for..." :search-for "Search for..."
:cancel "Cancel" :cancel "Cancel"
:next "Next" :next "Next"

View File

@ -34,7 +34,7 @@
:shh/restore-sym-keys {:web3 web3 :shh/restore-sym-keys {:web3 web3
:transport (:transport/chats db) :transport (:transport/chats db)
:on-success sym-key-added-callback}} :on-success sym-key-added-callback}}
(inbox/initialize-offline-inbox))))) (inbox/peers-summary-change-fx)))))
;;TODO (yenda) remove once go implements persistence ;;TODO (yenda) remove once go implements persistence
;;Since symkeys are not persisted, we restore them via add sym-keys, ;;Since symkeys are not persisted, we restore them via add sym-keys,

View File

@ -86,7 +86,7 @@
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id :sym-key-id] [:transport/chats chat-id :sym-key-id]
sym-key-id) sym-key-id)
:dispatch [:inbox/request-messages {:topics [topic]}] :dispatch [:inbox/request-messages {:topics [topic] :discover? false}]
:shh/add-filter {:web3 web3 :shh/add-filter {:web3 web3
:sym-key-id sym-key-id :sym-key-id sym-key-id
:topic topic :topic topic

View File

@ -11,8 +11,17 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[day8.re-frame.async-flow-fx] [status-im.constants :as constants]
[status-im.constants :as constants])) [status-im.utils.handlers-macro :as handlers-macro]))
(def connection-timeout
"Time after which mailserver connection is considered to have failed"
60000)
(def fetching-messages-notification-timeout
"Time after which we consider mailserver is done fetching messages and we can
stop showing notification to user"
5000)
(defn- parse-json (defn- parse-json
;; NOTE(dmitryn) Expects JSON response like: ;; NOTE(dmitryn) Expects JSON response like:
@ -48,61 +57,14 @@
wnode-id (get-in db [:account/account :settings :wnode chain])] wnode-id (get-in db [:account/account :settings :wnode chain])]
(get-in db [:inbox/wnodes chain wnode-id :address]))) (get-in db [:inbox/wnodes chain wnode-id :address])))
(defn initialize-offline-inbox-flow []
{:first-dispatch [:inbox/get-sym-key]
:rules [{:when :seen-both?
:events [:inbox/get-sym-key-success :inbox/connection-success]
:dispatch [:inbox/request-messages {:discover? true}]}]})
(defn recover-offline-inbox-flow []
{:first-dispatch [:inbox/fetch-peers]
:rules [{:when :seen?
:events :inbox/connection-success
:dispatch [:inbox/request-messages {:discover? true}]}]})
(defn initialize-offline-inbox
"Initialises offline inbox if inboxing enabled in config"
[{:keys [db]}]
(when config/offline-inbox-enabled?
(let [wnode (get-current-wnode-address db)]
(log/info "offline inbox: initialize " wnode)
(when wnode
{:async-flow (initialize-offline-inbox-flow)
:db (assoc db :mailserver-status :connecting)
::add-peer {:wnode wnode}}))))
(defn recover-offline-inbox
"Recover offline inbox connection after being offline because of connectivity loss"
[should-recover? {:keys [db]}]
(when (and config/offline-inbox-enabled?
should-recover?)
(let [wnode (get-current-wnode-address db)]
(when (and wnode
(:account/account db))
(log/info "offline inbox: recover" wnode)
{:db (assoc db :mailserver-status :connecting)
:async-flow (recover-offline-inbox-flow)}))))
(defn add-peer [enode success-fn error-fn]
(status/add-peer enode (response-handler error-fn success-fn)))
(defn fetch-peers
;; https://github.com/ethereum/go-ethereum/wiki/Management-APIs#admin_peers
;; retrieves all the information known about the connected remote nodes
;; TODO(dmitryn): use web3 instead of rpc call
[success-fn error-fn]
(let [args {:jsonrpc "2.0"
:id 2
:method "admin_peers"
:params []}
payload (.stringify js/JSON (clj->js args))]
(status/call-web3-private payload (response-handler error-fn success-fn))))
(defn registered-peer? [peers enode] (defn registered-peer? [peers enode]
(let [peer-ids (into #{} (map :id) peers) (let [peer-ids (into #{} (map :id) peers)
enode-id (transport.utils/extract-enode-id enode)] enode-id (transport.utils/extract-enode-id enode)]
(contains? peer-ids enode-id))) (contains? peer-ids enode-id)))
(defn add-peer [enode success-fn error-fn]
(status/add-peer enode (response-handler error-fn success-fn)))
(defn mark-trusted-peer [web3 enode success-fn error-fn] (defn mark-trusted-peer [web3 enode success-fn error-fn]
(.markTrustedPeer (transport.utils/shh web3) (.markTrustedPeer (transport.utils/shh web3)
enode enode
@ -111,7 +73,7 @@
(success-fn resp) (success-fn resp)
(error-fn err))))) (error-fn err)))))
(defn request-messages [web3 wnode topics to from sym-key-id success-fn error-fn] (defn request-inbox-messages [web3 wnode topics to from sym-key-id success-fn error-fn]
(let [opts (merge {:mailServerPeer wnode (let [opts (merge {:mailServerPeer wnode
:symKeyID sym-key-id} :symKeyID sym-key-id}
(when from {:from from}) (when from {:from from})
@ -119,7 +81,6 @@
(log/info "offline inbox: request-messages request for topics " topics) (log/info "offline inbox: request-messages request for topics " topics)
(doseq [topic topics] (doseq [topic topics]
(let [opts (assoc opts :topic topic)] (let [opts (assoc opts :topic topic)]
(log/info "offline inbox: request-messages args" (pr-str opts))
(.requestMessages (transport.utils/shh web3) (.requestMessages (transport.utils/shh web3)
(clj->js opts) (clj->js opts)
(fn [err resp] (fn [err resp]
@ -131,54 +92,122 @@
::add-peer ::add-peer
(fn [{:keys [wnode]}] (fn [{:keys [wnode]}]
(add-peer wnode (add-peer wnode
#(re-frame/dispatch [:inbox/fetch-peers]) #(log/debug "offline inbox: add-peer success" %)
#(log/error "offline inbox: add-peer error" %)))) #(log/error "offline inbox: add-peer error" %))))
(re-frame/reg-fx
::fetch-peers
(fn [retries]
(fetch-peers #(re-frame/dispatch [:inbox/check-peer-added % retries])
#(log/error "offline inbox: fetch-peers error" %))))
(re-frame/reg-fx (re-frame/reg-fx
::mark-trusted-peer ::mark-trusted-peer
(fn [{:keys [wnode web3]}] (fn [{:keys [wnode web3]}]
(mark-trusted-peer web3 (mark-trusted-peer web3
wnode wnode
#(re-frame/dispatch [:inbox/connection-success %]) #(re-frame/dispatch [:inbox/mailserver-trusted %])
#(log/error "offline inbox: mark-trusted-peer error" % wnode)))) #(re-frame/dispatch [:inbox/connection-check]))))
(re-frame/reg-fx (re-frame/reg-fx
::request-messages ::request-messages
(fn [{:keys [wnode topics to from sym-key-id web3]}] (fn [{:keys [wnode topics to from sym-key-id web3]}]
(request-messages web3 (request-inbox-messages web3
wnode wnode
topics topics
to to
from from
sym-key-id sym-key-id
#(log/info "offline inbox: request-messages response" %) #(log/info "offline inbox: request-messages response" %)
#(log/error "offline inbox: request-messages error" %1 %2 to from)))) #(log/error "offline inbox: request-messages error" %1 %2 to from))))
(defn update-mailserver-status [transition {:keys [db]}]
(let [state transition]
{:db (assoc db :mailserver-status state)}))
(defn generate-mailserver-symkey [{:keys [db] :as cofx}]
(when-not (:inbox/sym-key-id db)
{:shh/generate-sym-key-from-password
{:password (:inbox/password db)
:web3 (:web3 db)
:on-success (fn [_ sym-key-id]
(re-frame/dispatch [:inbox/get-sym-key-success sym-key-id]))
:on-error #(log/error "offline inbox: get-sym-key error" %)}}))
(defn connect-to-mailserver
"Add mailserver as a peer using ::add-peer cofx and generate sym-key when
it doesn't exists
Peer summary will change and we will receive a signal from status go when
this is successful
A connection-check is made after `connection timeout` is reached and
mailserver-status is changed to error if it is not connected by then"
[{:keys [db] :as cofx}]
(let [web3 (:web3 db)
wnode (get-current-wnode-address db)]
(when config/offline-inbox-enabled?
(handlers-macro/merge-fx cofx
{::add-peer {:wnode wnode}
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/connection-check]}]}
(update-mailserver-status :connecting)
(generate-mailserver-symkey)))))
(defn peers-summary-change-fx
"Called when a peer summary signal is received or we want to try to connect
to mailserver ie. after login.
Marks the mailserver as trusted peer if it is already added to the list of
peers or connects to it if it's not the case"
[{:keys [db] :as cofx}]
(when (and (:account/account db)
config/offline-inbox-enabled?)
(let [{:keys [peers-summary peers-count]} db]
(if (zero? peers-count)
(update-mailserver-status :disconnected cofx)
(let [wnode (get-current-wnode-address db)]
(if (registered-peer? peers-summary wnode)
(handlers-macro/merge-fx cofx
{::mark-trusted-peer {:web3 (:web3 db)
:wnode wnode}}
(generate-mailserver-symkey))
(connect-to-mailserver cofx)))))))
(defn get-topics
[db topics discover?]
(let [inbox-topics (:inbox/topics db)
discovery-topic (transport.utils/get-topic constants/contact-discovery)
topics (or topics
(map #(:topic %) (vals (:transport/chats db))))]
(cond-> (apply conj inbox-topics topics)
discover? (conj discovery-topic))))
(defn request-messages
([cofx]
(request-messages {} cofx))
([{:keys [topics discover? should-recover?]
:or {should-recover? true
discover? true}}
{:keys [db] :as cofx}]
(let [mailserver-status (:mailserver-status db)
sym-key-id (:inbox/sym-key-id db)
wnode (get-current-wnode-address db)
inbox-topics (get-topics db topics discover?)
inbox-ready? (and (= :connected mailserver-status)
sym-key-id)]
(when should-recover?
(if inbox-ready?
{::request-messages {:wnode wnode
:topics (into [] inbox-topics)
:sym-key-id sym-key-id
:web3 (:web3 db)}
:db (assoc db
:inbox/fetching? true
:inbox/topics #{})
:dispatch-later [{:ms fetching-messages-notification-timeout
:dispatch [:inbox/remove-fetching-notification]}]}
{:db (assoc db :inbox/topics (into #{} inbox-topics))})))))
;;;; Handlers ;;;; Handlers
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/add-peer :inbox/mailserver-trusted
;; This event adds a wnode to the list of peers (fn [{:keys [db] :as cofx} _]
(fn [_ [_ wnode]] (handlers-macro/merge-fx cofx
{::add-peer {:wnode wnode}})) (update-mailserver-status :connected)
(request-messages))))
(handlers/register-handler-fx
:inbox/fetch-peers
;; This event fetches the list of peers
;; We want it to check if the node has been added
(fn [_ [_ retries]]
{::fetch-peers (or retries 0)}))
(def ^:private ^:const short-retry-delay-ms 300)
(def ^:private ^:const long-retry-delay-ms 5000)
(def ^:private ^:const max-retries 10)
(def ^:private ^:const retries-interval-change-threshold 3)
(defn add-custom-mailservers [mailservers {:keys [db]}] (defn add-custom-mailservers [mailservers {:keys [db]}]
{:db (reduce (fn [db {:keys [id chain] :as mailserver}] {:db (reduce (fn [db {:keys [id chain] :as mailserver}]
@ -189,71 +218,30 @@
db db
mailservers)}) mailservers)})
(handlers/register-handler-fx
:inbox/check-peer-added
;; We check if the wnode is part of the peers list
;; if not we dispatch a new fetch-peer event for later
(fn [{{:keys [web3 network-status] :as db} :db} [_ peers retries]]
(let [wnode (get-current-wnode-address db)]
(log/info "offline inbox: fetch-peers response" peers)
(if (registered-peer? peers wnode)
{::mark-trusted-peer {:web3 web3
:wnode wnode}}
(do
(log/info "Peer" wnode "is not registered. Retrying fetch peers.")
(let [delay-ms (if (< retries retries-interval-change-threshold)
short-retry-delay-ms
long-retry-delay-ms)]
(if (or (= network-status :offline)
(> retries max-retries))
(do (log/info :mailserver-connection-error)
{:db (assoc db :mailserver-status :disconnected)})
{:dispatch-later [{:ms delay-ms :dispatch [:inbox/fetch-peers (inc retries)]}]})))))))
(handlers/register-handler-fx
:inbox/get-sym-key
(fn [{:keys [db]} _]
(let [web3 (:web3 db)
wnode (get-current-wnode-address db)
password (or (:password wnode)
(:inbox/password db))]
{:shh/generate-sym-key-from-password {:password password
:web3 web3
:on-success (fn [_ sym-key-id]
(re-frame/dispatch [:inbox/get-sym-key-success sym-key-id]))
:on-error #(log/error "offline inbox: get-sym-key error" %)}})))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/get-sym-key-success :inbox/get-sym-key-success
(fn [{:keys [db]} [_ sym-key-id]] (fn [{:keys [db] :as cofx} [_ sym-key-id]]
{:db (assoc db :inbox/sym-key-id sym-key-id)})) (handlers-macro/merge-fx cofx
{:db (assoc db :inbox/sym-key-id sym-key-id)}
(handlers/register-handler-fx (request-messages))))
:inbox/connection-success
(fn [{:keys [db]} _]
{:db (assoc db :mailserver-status :connected)}))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/request-messages :inbox/request-messages
(fn [{:keys [db now]} [_ {:keys [from topics discover?]}]] (fn [cofx [_ args]]
(let [web3 (:web3 db) (request-messages args cofx)))
wnode (get-current-wnode-address db)
topics (or topics (handlers/register-handler-fx
(map #(:topic %) (vals (:transport/chats db)))) :inbox/connection-check
from (or from (:inbox/last-request db) nil) (fn [{:keys [db] :as cofx} [_ _]]
sym-key-id (:inbox/sym-key-id db)] (when (= :connecting (:mailserver-status db))
{::request-messages {:wnode wnode (update-mailserver-status :error cofx))))
:topics (if discover?
(conj topics (transport.utils/get-topic constants/contact-discovery)) (handlers/register-handler-fx
topics) :inbox/remove-fetching-notification
;;TODO (yenda) fix from, right now mailserver is dropping us (fn [{:keys [db] :as cofx} [_ _]]
;;when we send a requestMessage with a from field {:db (dissoc db :inbox/fetching?)}))
;;:from from
:sym-key-id sym-key-id
:web3 web3}
:db (assoc db :inbox/last-request (quot now 1000))})))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/reconnect :inbox/reconnect
(fn [cofx _] (fn [cofx [_ args]]
(recover-offline-inbox true cofx))) (connect-to-mailserver cofx)))

View File

@ -41,5 +41,6 @@
(assoc :sym-key-id sym-key-id) (assoc :sym-key-id sym-key-id)
;;TODO (yenda) remove once go implements persistence ;;TODO (yenda) remove once go implements persistence
(assoc :sym-key sym-key))})] (assoc :sym-key sym-key))})]
:dispatch [:inbox/request-messages {:topics [topic] :dispatch [:inbox/request-messages {:topics [topic]
:from 0}]}))) :discover? false
:from 0}]})))

View File

@ -1,44 +1,29 @@
(ns status-im.ui.components.connectivity.view (ns status-im.ui.components.connectivity.view
(:require-macros [status-im.utils.views :refer [defview letsubs] :as views])
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.connectivity.styles :as styles] [status-im.ui.components.connectivity.styles :as styles]
[status-im.ui.components.animation :as animation]
[status-im.i18n :as i18n])) [status-im.i18n :as i18n]))
(def window-width (:width (react/get-dimensions "window"))) (def window-width (:width (react/get-dimensions "window")))
(defn start-error-animation [offline-opacity] (defview error-view [{:keys [top]}]
(animation/start (letsubs [offline? [:offline?]
(animation/timing offline-opacity {:toValue 1.0 disconnected? [:disconnected?]
:duration 250}))) mailserver-error? [:mailserver-error?]
fetching? [:fetching?]
(defn error-view [_] current-chat-contact [:get-current-chat-contact]
(let [offline? (re-frame/subscribe [:offline?]) view-id [:get :view-id]]
connection-problem? (re-frame/subscribe [:connection-problem?]) (when-let [label (cond
offline-opacity (animation/create-value 0.0) offline? :t/offline
on-update (fn [_ _] disconnected? :t/disconnected
(animation/set-value offline-opacity 0) mailserver-error? :t/mailserver-reconnect
(when (or @offline? @connection-problem?) fetching? :t/fetching-messages
(start-error-animation offline-opacity))) :else nil)]
current-chat-contact (re-frame/subscribe [:get-current-chat-contact]) (let [pending? (and (:pending current-chat-contact) (= :chat view-id))]
view-id (re-frame/subscribe [:get :view-id])] [react/view {:style (styles/text-wrapper top 1.0 window-width pending?)}
(reagent/create-class [react/text {:style styles/text
{:component-did-mount :on-press (when mailserver-error?
on-update #(re-frame/dispatch [:inbox/reconnect]))}
:component-did-update (i18n/label label)]]))))
on-update
:display-name "connectivity-error-view"
:reagent-render
(fn [{:keys [top]}]
(when-let [label (cond
@offline? :t/offline
@connection-problem? :t/mailserver-reconnect
:else nil)]
(let [pending? (and (:pending @current-chat-contact) (= :chat @view-id))]
[react/animated-view {:style (styles/text-wrapper top offline-opacity window-width pending?)}
[react/view
[react/text {:style styles/text
:on-press (when @connection-problem?
#(re-frame/dispatch [:inbox/reconnect]))}
(i18n/label label)]]])))})))

View File

@ -37,9 +37,12 @@
:wallet.transactions constants/default-wallet-transactions :wallet.transactions constants/default-wallet-transactions
:wallet-selected-asset {} :wallet-selected-asset {}
:prices {} :prices {}
:peers-count 0
:peers-summary []
:notifications {} :notifications {}
:network constants/default-network :network constants/default-network
:networks/networks constants/default-networks :networks/networks constants/default-networks
:inbox/topics #{}
:inbox/wnodes constants/default-wnodes :inbox/wnodes constants/default-wnodes
:inbox/password constants/inbox-password :inbox/password constants/inbox-password
:my-profile/editing? false :my-profile/editing? false
@ -69,7 +72,7 @@
(spec/def ::network-status (spec/nilable keyword?)) (spec/def ::network-status (spec/nilable keyword?))
(spec/def ::mailserver-status (spec/nilable keyword?)) (spec/def ::mailserver-status (spec/nilable keyword?))
(spec/def ::peers-count (spec/nilable integer?)) (spec/def :inbox/topics set?)
;;;;NODE ;;;;NODE
@ -124,6 +127,9 @@
;;;;NETWORK ;;;;NETWORK
(spec/def ::network (spec/nilable string?)) (spec/def ::network (spec/nilable string?))
(spec/def ::peers-count (spec/nilable integer?))
(spec/def ::peers-summary (spec/nilable vector?))
(spec/def :inbox/fetching? (spec/nilable boolean?))
;;;;NODE ;;;;NODE
@ -168,9 +174,11 @@
:node/after-start :node/after-start
:node/after-stop :node/after-stop
:inbox/wnodes :inbox/wnodes
:inbox/topics
:inbox/password :inbox/password
:inbox/sym-key-id :inbox/sym-key-id
:inbox/last-request :inbox/last-request
:inbox/fetching?
:browser/browsers :browser/browsers
:browser/options :browser/options
:new/open-dapp :new/open-dapp
@ -195,6 +203,7 @@
::network-status ::network-status
::mailserver-status ::mailserver-status
::peers-count ::peers-count
::peers-summary
::sync-listening-started ::sync-listening-started
::sync-state ::sync-state
::sync-data ::sync-data

View File

@ -270,13 +270,15 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:initialize-db :initialize-db
(fn [{{:keys [status-module-initialized? status-node-started? (fn [{{:keys [status-module-initialized? status-node-started?
network-status network device-UUID] network-status network peers-count peers-summary device-UUID]
:or {network (get app-db :network)}} :db} :or {network (get app-db :network)}} :db}
[_ encryption-key]] [_ encryption-key]]
{::init-store encryption-key {::init-store encryption-key
:db (assoc app-db :db (assoc app-db
:contacts/contacts {} :contacts/contacts {}
:network-status network-status :network-status network-status
:peers-count peers-count
:peers-summary peers-summary
:status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?)
:status-node-started? status-node-started? :status-node-started? status-node-started?
:network network :network network
@ -285,7 +287,7 @@
(handlers/register-handler-db (handlers/register-handler-db
:initialize-account-db :initialize-account-db
(fn [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks (fn [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks
network network-status view-id navigation-stack network network-status peers-count peers-summary view-id navigation-stack
access-scope->commands-responses access-scope->commands-responses
status-module-initialized? status-node-started? device-UUID] status-module-initialized? status-node-started? device-UUID]
:or [network (get app-db :network)]} [_ address]] :or [network (get app-db :network)]} [_ address]]
@ -303,6 +305,8 @@
:account/account current-account :account/account current-account
:network-status network-status :network-status network-status
:network network :network network
:peers-summary peers-summary
:peers-count peers-count
:device-UUID device-UUID) :device-UUID device-UUID)
console-contact console-contact
(assoc :contacts/contacts {constants/console-chat-id console-contact}))))) (assoc :contacts/contacts {constants/console-chat-id console-contact})))))
@ -398,6 +402,16 @@
{:result {:returned (dissoc data :origParams)}}]) {:result {:returned (dissoc data :origParams)}}])
(log/debug "Unknown jail signal " event)))) (log/debug "Unknown jail signal " event))))
(handlers/register-handler-fx
:discovery/summary
(fn [{:keys [db] :as cofx} [_ peers-summary]]
(let [peers-count (count peers-summary)]
(handlers-macro/merge-fx cofx
{:db (assoc db
:peers-summary peers-summary
:peers-count peers-count)}
(inbox/peers-summary-change-fx)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:signal-event :signal-event
(fn [_ [_ event-str]] (fn [_ [_ event-str]]
@ -407,12 +421,13 @@
to-dispatch (case type to-dispatch (case type
"sign-request.queued" [:sign-request-queued event] "sign-request.queued" [:sign-request-queued event]
"sign-request.failed" [:sign-request-failed event] "sign-request.failed" [:sign-request-failed event]
"node.started" [:status-node-started] "node.started" [:status-node-started]
"node.stopped" [:status-node-stopped] "node.stopped" [:status-node-stopped]
"module.initialized" [:status-module-initialized] "module.initialized" [:status-module-initialized]
"jail.signal" (handle-jail-signal event) "jail.signal" (handle-jail-signal event)
"envelope.sent" [:signals/envelope-status (:hash event) :sent] "envelope.sent" [:signals/envelope-status (:hash event) :sent]
"envelope.expired" [:signals/envelope-status (:hash event) :not-sent] "envelope.expired" [:signals/envelope-status (:hash event) :not-sent]
"discovery.summary" [:discovery/summary event]
(log/debug "Event " type " not handled"))] (log/debug "Event " type " not handled"))]
(when to-dispatch (when to-dispatch
{:dispatch to-dispatch})))) {:dispatch to-dispatch}))))
@ -437,13 +452,11 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:app-state-change :app-state-change
(fn [{{:keys [network-status mailserver-status]} :db :as cofx} [_ state]] (fn [{{:keys [network-status mailserver-status]} :db :as cofx} [_ state]]
(let [app-coming-from-background? (= state "active") (let [app-coming-from-background? (= state "active")]
should-recover? (and app-coming-from-background?
(= network-status :online)
(not= mailserver-status :connecting))]
(handlers-macro/merge-fx cofx (handlers-macro/merge-fx cofx
{::app-state-change-fx state} {::app-state-change-fx state}
(inbox/recover-offline-inbox should-recover?))))) (inbox/request-messages {:should-recover? app-coming-from-background?
:discover? true})))))
(handlers/register-handler-fx (handlers/register-handler-fx
:request-permissions :request-permissions

View File

@ -44,6 +44,10 @@
(reg-sub :peers-count :peers-count) (reg-sub :peers-count :peers-count)
(reg-sub :mailserver-status :mailserver-status) (reg-sub :mailserver-status :mailserver-status)
(reg-sub :fetching?
(fn [db]
(get db :inbox/fetching?)))
(reg-sub :offline? (reg-sub :offline?
:<- [:network-status] :<- [:network-status]
:<- [:sync-state] :<- [:sync-state]
@ -51,12 +55,15 @@
(or (= network-status :offline) (or (= network-status :offline)
(= sync-state :offline)))) (= sync-state :offline))))
(reg-sub :connection-problem? (reg-sub :disconnected?
:<- [:mailserver-status]
:<- [:peers-count] :<- [:peers-count]
(fn [[mailserver-status peers-count]] (fn [peers-count]
(or (= :disconnected mailserver-status) (zero? peers-count)))
(zero? peers-count))))
(reg-sub :mailserver-error?
:<- [:mailserver-status]
(fn [mailserver-status]
(#{:error :disconnected} mailserver-status)))
(reg-sub :syncing? (reg-sub :syncing?
:<- [:sync-state] :<- [:sync-state]

View File

@ -21,7 +21,7 @@
(def testfairy-enabled? (enabled? (get-config :TESTFAIRY_ENABLED))) (def testfairy-enabled? (enabled? (get-config :TESTFAIRY_ENABLED)))
(def stub-status-go? (enabled? (get-config :STUB_STATUS_GO 0))) (def stub-status-go? (enabled? (get-config :STUB_STATUS_GO 0)))
(def mainnet-warning-enabled? (enabled? (get-config :MAINNET_WARNING_ENABLED 0))) (def mainnet-warning-enabled? (enabled? (get-config :MAINNET_WARNING_ENABLED 0)))
(def offline-inbox-enabled? (enabled? (get-config :OFFLINE_INBOX_ENABLED 0))) (def offline-inbox-enabled? (enabled? (get-config :OFFLINE_INBOX_ENABLED "1")))
(def log-level (def log-level
(-> (get-config :LOG_LEVEL "error") (-> (get-config :LOG_LEVEL "error")
string/lower-case string/lower-case

View File

@ -1,6 +1,7 @@
(ns status-im.utils.utils (ns status-im.utils.utils
(:require [status-im.i18n :as i18n] (:require [status-im.i18n :as i18n]
[status-im.react-native.js-dependencies :as rn-dependencies])) [status-im.react-native.js-dependencies :as rn-dependencies]
[re-frame.core :as re-frame]))
(defn show-popup (defn show-popup
([title content] ([title content]
@ -59,6 +60,14 @@
(defn set-timeout [cb ms] (defn set-timeout [cb ms]
(.setTimeout rn-dependencies/background-timer cb ms)) (.setTimeout rn-dependencies/background-timer cb ms))
;; same as re-frame dispatch-later but using background timer for long
;; running timeouts
(re-frame/reg-fx
:utils/dispatch-later
(fn [params]
(doseq [{:keys [ms dispatch]} params]
(set-timeout #(re-frame/dispatch dispatch) ms))))
(defn clear-timeout [id] (defn clear-timeout [id]
(.clearTimeout rn-dependencies/background-timer id)) (.clearTimeout rn-dependencies/background-timer id))

View File

@ -18,6 +18,7 @@
[status-im.test.chat.subs] [status-im.test.chat.subs]
[status-im.test.chat.views.message] [status-im.test.chat.views.message]
[status-im.test.i18n] [status-im.test.i18n]
[status-im.test.transport.inbox]
[status-im.test.protocol.web3.inbox] [status-im.test.protocol.web3.inbox]
[status-im.test.utils.utils] [status-im.test.utils.utils]
[status-im.test.utils.money] [status-im.test.utils.money]
@ -62,6 +63,7 @@
'status-im.test.chat.models.message 'status-im.test.chat.models.message
'status-im.test.chat.views.message 'status-im.test.chat.views.message
'status-im.test.i18n 'status-im.test.i18n
'status-im.test.transport.inbox
'status-im.test.protocol.web3.inbox 'status-im.test.protocol.web3.inbox
'status-im.test.utils.utils 'status-im.test.utils.utils
'status-im.test.utils.money 'status-im.test.utils.money

View File

@ -0,0 +1,80 @@
(ns status-im.test.transport.inbox
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.transport.inbox :as inbox]
[status-im.constants :as constants]))
(deftest request-messages
(testing "mailserver not connected"
(is (= (inbox/request-messages {} {:db {:mailserver-status :connecting :inbox/sym-key-id :sym-key}})
{:db
{:mailserver-status :connecting,
:inbox/sym-key-id :sym-key,
:inbox/topics #{"0xf8946aac"}}}))
(is (= (inbox/request-messages {:discover? false :topics ["Oxaaaaaaaa"]} {:db {:mailserver-status :connecting :inbox/sym-key-id :sym-key}})
{:db
{:mailserver-status :connecting,
:inbox/sym-key-id :sym-key,
:inbox/topics #{"Oxaaaaaaaa"}}})))
(testing "mailserver is connected"
(is (= (inbox/request-messages {} {:db {:mailserver-status :connected :inbox/sym-key-id :sym-key}})
{:status-im.transport.inbox/request-messages
{:wnode nil, :topics ["0xf8946aac"], :sym-key-id :sym-key, :web3 nil},
:db
{:mailserver-status :connected,
:inbox/sym-key-id :sym-key,
:inbox/fetching? true,
:inbox/topics #{}},
:dispatch-later
[{:ms 5000, :dispatch [:inbox/remove-fetching-notification]}]})
(= (inbox/request-messages {:discover? false :topics ["Oxaaaaaaaa"]} {:db {:mailserver-status :connected :inbox/sym-key-id :sym-key}})
{:status-im.transport.inbox/request-messages
{:wnode nil, :topics ["Oxaaaaaaaa"], :sym-key-id :sym-key, :web3 nil},
:db
{:mailserver-status :connected,
:inbox/sym-key-id :sym-key,
:inbox/fetching? true,
:inbox/topics #{}},
:dispatch-later
[{:ms 5000, :dispatch [:inbox/remove-fetching-notification]}]}))))
(defn cofx-fixtures [sym-key peers-count registered-peer?]
{:db {:mailserver-status :connected
:inbox/sym-key-id sym-key
:network "mainnet_rpc"
:peers-count peers-count
:peers-summary (if registered-peer?
[{:id "wnode-id"}]
[])
:account/account {:networks constants/default-networks
:settings {:wnode {:mainnet "mailserver-a"}}}
:inbox/wnodes {:mainnet {"mailserver-a" {:address "enode://wnode-id@ip"}}}}})
(defn peers-summary-change-fx-result [sym-key peers-count registered-peer?]
(update-in (inbox/peers-summary-change-fx (cofx-fixtures sym-key peers-count registered-peer?))
[:db] dissoc :account/account :inbox/wnodes :peers-summary :peers-count))
(deftest peers-summary-change-fx
(testing "Mailserver is connected and sym-key doesn't exists"
(let [result (peers-summary-change-fx-result false 1 true)]
(is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/mark-trusted-peer :shh/generate-sym-key-from-password}))))
(testing "Mailserver is connected and sym-key exists"
(let [result (peers-summary-change-fx-result true 1 true)]
(is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/mark-trusted-peer}))))
(testing "Mailserver is not connected and sym-key doesn't exists"
(let [result (peers-summary-change-fx-result false 1 false)]
(is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(testing "Mailserver is not connected and sym-key exists"
(let [result (peers-summary-change-fx-result true 1 false)]
(is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(testing "App is not connected to any peer"
(is (= (get-in (peers-summary-change-fx-result true 0 true)
[:db :mailserver-status])
:disconnected))))