remove merge-fx macro

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2018-09-24 17:59:02 +02:00
parent 3486a0f5e6
commit 4bd5d986b0
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
99 changed files with 1753 additions and 1981 deletions

View File

@ -5,10 +5,10 @@
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.wallet.settings.models :as wallet.settings.models] [status-im.ui.screens.wallet.settings.models :as wallet.settings.models]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.utils :as utils]
[status-im.utils.utils :as utils])) [status-im.utils.fx :as fx]))
(defn show-mainnet-is-default-alert [{:keys [db]}] (fx/defn show-mainnet-is-default-alert [{:keys [db]}]
(let [enter-name-screen? (= :enter-name (get-in db [:accounts/create :step])) (let [enter-name-screen? (= :enter-name (get-in db [:accounts/create :step]))
shown? (get-in db [:account/account :mainnet-warning-shown?])] shown? (get-in db [:account/account :mainnet-warning-shown?])]
(when (and config/mainnet-warning-enabled? (when (and config/mainnet-warning-enabled?
@ -24,29 +24,31 @@
(not (:in-progress? transaction)) (not (:in-progress? transaction))
(:from-chat? transaction))) (:from-chat? transaction)))
(defn continue-after-wallet-onboarding [db modal? cofx] (fx/defn continue-after-wallet-onboarding [{:keys [db] :as cofx} modal?]
(let [transaction (get-in db [:wallet :send-transaction])] (let [transaction (get-in db [:wallet :send-transaction])]
(if modal? (if modal?
{:dispatch [:navigate-to-clean :wallet-send-transaction-modal]} {:dispatch [:navigate-to-clean :wallet-send-transaction-modal]}
(if-not (chat-send? transaction) (if-not (chat-send? transaction)
(navigation/navigate-to-clean :wallet cofx) (navigation/navigate-to-clean cofx :wallet nil)
(navigation/navigate-to-cofx :wallet-send-transaction-modal nil cofx))))) (navigation/navigate-to-cofx cofx :wallet-send-transaction-modal nil)))))
(defn confirm-wallet-set-up [modal? {:keys [db] :as cofx}] (fx/defn confirm-wallet-set-up
(handlers-macro/merge-fx [{:keys [db] :as cofx} modal?]
cofx (fx/merge cofx
(continue-after-wallet-onboarding db modal?) (continue-after-wallet-onboarding modal?)
(wallet.settings.models/wallet-autoconfig-tokens) (wallet.settings.models/wallet-autoconfig-tokens)
(accounts.update/account-update {:wallet-set-up-passed? true}))) (accounts.update/account-update {:wallet-set-up-passed? true} {})))
(defn switch-dev-mode [dev-mode? cofx] (fx/defn switch-dev-mode [cofx dev-mode?]
(merge (accounts.update/account-update {:dev-mode? dev-mode?} cofx) (merge (accounts.update/account-update cofx
{:dev-mode? dev-mode?}
{})
(if dev-mode? (if dev-mode?
{:dev-server/start nil} {:dev-server/start nil}
{:dev-server/stop nil}))) {:dev-server/stop nil})))
(defn switch-web3-opt-in-mode [opt-in {:keys [db] :as cofx}] (fx/defn switch-web3-opt-in-mode [{:keys [db] :as cofx} opt-in]
(let [settings (get-in db [:account/account :settings])] (let [settings (get-in db [:account/account :settings])]
(accounts.update/update-settings (accounts.update/update-settings cofx
(assoc settings :web3-opt-in? opt-in) (assoc settings :web3-opt-in? opt-in)
cofx))) {})))

View File

@ -13,12 +13,12 @@
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.random :as random] [status-im.utils.random :as random]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.hex :as utils.hex] [status-im.utils.hex :as utils.hex]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.signing-phrase.core :as signing-phrase] [status-im.utils.signing-phrase.core :as signing-phrase]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn get-signing-phrase [cofx] (defn get-signing-phrase [cofx]
(assoc cofx :signing-phrase (signing-phrase/generate))) (assoc cofx :signing-phrase (signing-phrase/generate)))
@ -37,9 +37,9 @@
{:db (update db :accounts/create assoc :step :account-creating :error nil) {:db (update db :accounts/create assoc :step :account-creating :error nil)
:accounts.create/create-account (:password create)}) :accounts.create/create-account (:password create)})
(defn- add-account (fx/defn add-account
"Takes db and new account, creates map of effects describing adding account to database and realm" "Takes db and new account, creates map of effects describing adding account to database and realm"
[{:keys [address] :as account} cofx] [cofx {:keys [address] :as account}]
(let [db (:db cofx) (let [db (:db cofx)
{:networks/keys [networks]} db {:networks/keys [networks]} db
enriched-account (assoc account enriched-account (assoc account
@ -49,10 +49,12 @@
{:db (assoc-in db [:accounts/accounts address] enriched-account) {:db (assoc-in db [:accounts/accounts address] enriched-account)
:data-store/base-tx [(accounts-store/save-account-tx enriched-account)]})) :data-store/base-tx [(accounts-store/save-account-tx enriched-account)]}))
(defn on-account-created [{:keys [pubkey address mnemonic]} password seed-backed-up {:keys [random-guid-generator (fx/defn on-account-created
signing-phrase [{:keys [random-guid-generator
status signing-phrase
db] :as cofx}] status
db] :as cofx}
{:keys [pubkey address mnemonic]} password seed-backed-up]
(let [normalized-address (utils.hex/normalize-hex address) (let [normalized-address (utils.hex/normalize-hex address)
account {:public-key pubkey account {:public-key pubkey
:installation-id (random-guid-generator) :installation-id (random-guid-generator)
@ -67,12 +69,12 @@
:settings (constants/default-account-settings)}] :settings (constants/default-account-settings)}]
(log/debug "account-created") (log/debug "account-created")
(when-not (string/blank? pubkey) (when-not (string/blank? pubkey)
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :accounts/login {:address normalized-address {:db (assoc db :accounts/login {:address normalized-address
:password password :password password
:processing true})} :processing true})}
(add-account account) (add-account account)
(accounts.login/user-login))))) (accounts.login/user-login)))))
(defn reset-account-creation [{db :db}] (defn reset-account-creation [{db :db}]
{:db (update db :accounts/create assoc {:db (update db :accounts/create assoc
@ -81,17 +83,19 @@
:password-confirm nil :password-confirm nil
:error nil)}) :error nil)})
(defn account-set-input-text [input-key text {db :db}] (fx/defn account-set-input-text
[{db :db} input-key text]
{:db (update db :accounts/create merge {input-key text :error nil})}) {:db (update db :accounts/create merge {input-key text :error nil})})
(defn account-set-name [{{:accounts/keys [create] :as db} :db :as cofx}] (defn account-set-name [{{:accounts/keys [create] :as db} :db :as cofx}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :accounts/create {:show-welcome? true}) {:db (assoc db :accounts/create {:show-welcome? true})
:notifications/request-notifications-permissions nil :notifications/request-notifications-permissions nil
:dispatch [:navigate-to :home]} :dispatch [:navigate-to :home]}
(accounts.update/account-update {:name (:name create)}))) (accounts.update/account-update {:name (:name create)} {})))
(defn next-step [step password password-confirm {:keys [db] :as cofx}] (fx/defn next-step
[{:keys [db] :as cofx} step password password-confirm]
(case step (case step
:enter-password {:db (assoc-in db [:accounts/create :step] :confirm-password)} :enter-password {:db (assoc-in db [:accounts/create :step] :confirm-password)}
:confirm-password (if (= password password-confirm) :confirm-password (if (= password password-confirm)
@ -99,22 +103,25 @@
{:db (assoc-in db [:accounts/create :error] (i18n/label :t/password_error1))}) {:db (assoc-in db [:accounts/create :error] (i18n/label :t/password_error1))})
:enter-name (account-set-name cofx))) :enter-name (account-set-name cofx)))
(defn step-back [step cofx] (fx/defn step-back
[cofx step]
(case step (case step
:enter-password (navigation/navigate-back cofx) :enter-password (navigation/navigate-back cofx)
:confirm-password (reset-account-creation cofx))) :confirm-password (reset-account-creation cofx)))
(defn navigate-to-create-account-screen [{:keys [db] :as cofx}] (fx/defn navigate-to-create-account-screen
(handlers-macro/merge-fx cofx [{:keys [db] :as cofx}]
{:db (update db :accounts/create (fx/merge cofx
#(-> % {:db (update db :accounts/create
(assoc :step :enter-password) #(-> %
(dissoc :password :password-confirm :name :error)))} (assoc :step :enter-password)
(navigation/navigate-to-cofx :create-account nil))) (dissoc :password :password-confirm :name :error)))}
(navigation/navigate-to-cofx :create-account nil)))
(defn navigate-to-authentication-method [{:keys [db] :as cofx}] (fx/defn navigate-to-authentication-method
[{:keys [db] :as cofx}]
(if (hardwallet/hardwallet-supported? db) (if (hardwallet/hardwallet-supported? db)
(navigation/navigate-to-cofx :hardwallet-authentication-method nil cofx) (navigation/navigate-to-cofx cofx :hardwallet-authentication-method nil)
(navigate-to-create-account-screen cofx))) (navigate-to-create-account-screen cofx)))
;;;; COFX ;;;; COFX

View File

@ -5,7 +5,7 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.node.core :as node] [status-im.node.core :as node]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.fx :as fx]
[status-im.utils.keychain.core :as keychain] [status-im.utils.keychain.core :as keychain]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
@ -35,16 +35,17 @@
(re-frame/dispatch [:init.callback/account-change-error]))))) (re-frame/dispatch [:init.callback/account-change-error])))))
;;;; Handlers ;;;; Handlers
(defn login [cofx] (fx/defn login [cofx]
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)] (let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
{:accounts.login/login [address password save-password?]})) {:accounts.login/login [address password save-password?]}))
(defn user-login [{:keys [db] :as cofx}] (fx/defn user-login [{:keys [db] :as cofx}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:accounts/login :processing] true)} {:db (assoc-in db [:accounts/login :processing] true)}
(node/initialize (get-in db [:accounts/login :address])))) (node/initialize (get-in db [:accounts/login :address]))))
(defn user-login-callback [login-result {db :db :as cofx}] (fx/defn user-login-callback
[{db :db :as cofx} login-result]
(let [data (types/json->clj login-result) (let [data (types/json->clj login-result)
error (:error data) error (:error data)
success (empty? error)] success (empty? error)]
@ -58,7 +59,7 @@
:error error :error error
:processing false)}))) :processing false)})))
(defn open-login [address photo-path name {:keys [db]}] (fx/defn open-login [{:keys [db]} address photo-path name]
{:db (-> db {:db (-> db
(update :accounts/login assoc (update :accounts/login assoc
:address address :address address
@ -71,14 +72,14 @@
:keychain/get-user-password [address :keychain/get-user-password [address
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success %])]}) #(re-frame/dispatch [:accounts.login.callback/get-user-password-success %])]})
(defn open-login-callback (fx/defn open-login-callback
[password {:keys [db] :as cofx}] [{:keys [db] :as cofx} password]
(if password (if password
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:accounts/login :password] password)} {:db (assoc-in db [:accounts/login :password] password)}
(navigation/navigate-to-cofx :progress nil) (navigation/navigate-to-cofx :progress nil)
(user-login)) (user-login))
(navigation/navigate-to-clean :login cofx))) (navigation/navigate-to-clean cofx :login nil)))
(re-frame/reg-fx (re-frame/reg-fx
:accounts.login/login :accounts.login/login

View File

@ -4,20 +4,19 @@
[status-im.init.core :as init] [status-im.init.core :as init]
[status-im.transport.core :as transport] [status-im.transport.core :as transport]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn logout (fx/defn logout
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:transport/keys [chats]} db] (let [{:transport/keys [chats]} db]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:keychain/clear-user-password (get-in db [:account/account :address])
{:keychain/clear-user-password (get-in db [:account/account :address]) :dev-server/stop nil}
:dev-server/stop nil} (navigation/navigate-to-clean :login {})
(navigation/navigate-to-clean :login) (transport/stop-whisper)
(transport/stop-whisper) (init/initialize-keychain))))
(init/initialize-keychain))))
(defn show-logout-confirmation [] (fx/defn show-logout-confirmation [_]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :t/logout-title) {:title (i18n/label :t/logout-title)
:content (i18n/label :t/logout-are-you-sure) :content (i18n/label :t/logout-are-you-sure)

View File

@ -7,10 +7,10 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.ethereum.mnemonic :as mnemonic] [status-im.utils.ethereum.mnemonic :as mnemonic]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types])) [status-im.utils.types :as types]
[status-im.utils.fx :as fx]))
(defn check-password-errors [password] (defn check-password-errors [password]
(cond (string/blank? password) :required-field (cond (string/blank? password) :required-field
@ -37,49 +37,55 @@
(types/clj->json))] (types/clj->json))]
(re-frame/dispatch [:accounts.recover.callback/recover-account-success data password]))))) (re-frame/dispatch [:accounts.recover.callback/recover-account-success data password])))))
(defn set-phrase [masked-recovery-phrase {:keys [db]}] (fx/defn set-phrase
[{:keys [db]} masked-recovery-phrase]
(let [recovery-phrase (security/unmask masked-recovery-phrase)] (let [recovery-phrase (security/unmask masked-recovery-phrase)]
{:db (update db :accounts/recover assoc {:db (update db :accounts/recover assoc
:passphrase (string/lower-case recovery-phrase) :passphrase (string/lower-case recovery-phrase)
:passphrase-valid? (not (check-phrase-errors recovery-phrase)))})) :passphrase-valid? (not (check-phrase-errors recovery-phrase)))}))
(defn validate-phrase [{:keys [db]}] (fx/defn validate-phrase
[{:keys [db]}]
(let [recovery-phrase (get-in db [:accounts/recover :passphrase])] (let [recovery-phrase (get-in db [:accounts/recover :passphrase])]
{:db (update db :accounts/recover assoc {:db (update db :accounts/recover assoc
:passphrase-error (check-phrase-errors recovery-phrase) :passphrase-error (check-phrase-errors recovery-phrase)
:passphrase-warning (check-phrase-warnings recovery-phrase))})) :passphrase-warning (check-phrase-warnings recovery-phrase))}))
(defn set-password [masked-password {:keys [db]}] (fx/defn set-password
[{:keys [db]} masked-password]
(let [password (security/unmask masked-password)] (let [password (security/unmask masked-password)]
{:db (update db :accounts/recover assoc {:db (update db :accounts/recover assoc
:password password :password password
:password-valid? (not (check-password-errors password)))})) :password-valid? (not (check-password-errors password)))}))
(defn validate-password [{:keys [db]}] (fx/defn validate-password
[{:keys [db]}]
(let [password (get-in db [:accounts/recover :password])] (let [password (get-in db [:accounts/recover :password])]
{:db (assoc-in db [:accounts/recover :password-error] (check-password-errors password))})) {:db (assoc-in db [:accounts/recover :password-error] (check-password-errors password))}))
(defn validate-recover-result [{:keys [error pubkey address]} password {:keys [db] :as cofx}] (fx/defn validate-recover-result
[{:keys [db] :as cofx} {:keys [error pubkey address]} password]
(if (empty? error) (if (empty? error)
(let [account {:pubkey pubkey (let [account {:pubkey pubkey
:address address :address address
:photo-path (identicon/identicon pubkey) :photo-path (identicon/identicon pubkey)
:mnemonic ""}] :mnemonic ""}]
(accounts.create/on-account-created account password true cofx)) (accounts.create/on-account-created cofx account password true))
{:db (assoc-in db [:accounts/recover :password-error] :recover-password-invalid)})) {:db (assoc-in db [:accounts/recover :password-error] :recover-password-invalid)}))
(defn on-account-recovered [result password {:keys [db] :as cofx}] (fx/defn on-account-recovered
[{:keys [db] :as cofx} result password]
(let [data (types/json->clj result)] (let [data (types/json->clj result)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (dissoc db :accounts/recover)} {:db (dissoc db :accounts/recover)}
(validate-recover-result data password)))) (validate-recover-result data password))))
(defn recover-account [{:keys [db]}] (fx/defn recover-account [{:keys [db]}]
(let [{:keys [password passphrase]} (:accounts/recover db)] (let [{:keys [password passphrase]} (:accounts/recover db)]
{:db (assoc-in db [:accounts/recover :processing?] true) {:db (assoc-in db [:accounts/recover :processing?] true)
:accounts.recover/recover-account [(security/mask-data passphrase) password]})) :accounts.recover/recover-account [(security/mask-data passphrase) password]}))
(defn recover-account-with-checks [{:keys [db] :as cofx}] (fx/defn recover-account-with-checks [{:keys [db] :as cofx}]
(let [{:keys [passphrase processing?]} (:accounts/recover db)] (let [{:keys [passphrase processing?]} (:accounts/recover db)]
(when-not processing? (when-not processing?
(if (mnemonic/status-generated-phrase? passphrase) (if (mnemonic/status-generated-phrase? passphrase)
@ -90,10 +96,10 @@
:confirm-button-text (i18n/label :recovery-confirm-phrase) :confirm-button-text (i18n/label :recovery-confirm-phrase)
:on-accept #(re-frame/dispatch [:accounts.recover.ui/recover-account-confirmed])}})))) :on-accept #(re-frame/dispatch [:accounts.recover.ui/recover-account-confirmed])}}))))
(defn navigate-to-recover-account-screen [{:keys [db] :as cofx}] (fx/defn navigate-to-recover-account-screen [{:keys [db] :as cofx}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (dissoc db :accounts/recover)} {:db (dissoc db :accounts/recover)}
(navigation/navigate-to-cofx :recover nil))) (navigation/navigate-to-cofx :recover nil)))
(re-frame/reg-fx (re-frame/reg-fx
:accounts.recover/recover-account :accounts.recover/recover-account

View File

@ -2,43 +2,40 @@
(:require [status-im.data-store.accounts :as accounts-store] (:require [status-im.data-store.accounts :as accounts-store]
[status-im.transport.message.core :as transport] [status-im.transport.message.core :as transport]
[status-im.transport.message.v1.contact :as message.contact] [status-im.transport.message.v1.contact :as message.contact]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn account-update (fx/defn account-update
"Takes effects (containing :db) + new account fields, adds all effects necessary for account update. "Takes effects (containing :db) + new account fields, adds all effects necessary for account update.
Optionally, one can specify a success-event to be dispatched after fields are persisted." Optionally, one can specify a success-event to be dispatched after fields are persisted."
([new-account-fields cofx] [{:keys [db] :as cofx} new-account-fields {:keys [success-event]}]
(account-update new-account-fields nil cofx)) (let [current-account (:account/account db)
([new-account-fields success-event {:keys [db] :as cofx}] new-account (merge current-account new-account-fields)
(let [current-account (:account/account db) fcm-token (get-in db [:notifications :fcm-token])
new-account (merge current-account new-account-fields) fx {:db (assoc db :account/account new-account)
fcm-token (get-in db [:notifications :fcm-token]) :data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
fx {:db (assoc db :account/account new-account) :success-event success-event}]}
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account) {:keys [name photo-path address]} new-account]
:success-event success-event}]} (if (or (:name new-account-fields) (:photo-path new-account-fields))
{:keys [name photo-path address]} new-account] (fx/merge cofx
(if (or (:name new-account-fields) (:photo-path new-account-fields)) fx
(handlers-macro/merge-fx #(transport/send (message.contact/ContactUpdate. name photo-path address fcm-token) nil %))
cofx fx)))
fx
(transport/send (message.contact/ContactUpdate. name photo-path address fcm-token) nil))
fx))))
(defn clean-seed-phrase (fx/defn clean-seed-phrase
"A helper function that removes seed phrase from storage." "A helper function that removes seed phrase from storage."
[cofx] [cofx]
(account-update {:seed-backed-up? true (account-update cofx
{:seed-backed-up? true
:mnemonic nil} :mnemonic nil}
cofx)) {}))
(defn update-sign-in-time (fx/defn update-sign-in-time
[{db :db now :now :as cofx}] [{db :db now :now :as cofx}]
(account-update {:last-sign-in now} cofx)) (account-update cofx {:last-sign-in now} {}))
(defn update-settings (fx/defn update-settings
([settings cofx] (update-settings settings nil cofx)) [{{:keys [account/account] :as db} :db :as cofx} settings {:keys [success-event]}]
([settings success-event {{:keys [account/account] :as db} :db :as cofx}] (let [new-account (assoc account :settings settings)]
(let [new-account (assoc account :settings settings)] {:db (assoc db :account/account new-account)
{:db (assoc db :account/account new-account) :data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account) :success-event success-event}]}))
:success-event success-event}]})))

View File

@ -4,7 +4,7 @@
[status-im.accounts.update.core :as accounts.update] [status-im.accounts.update.core :as accounts.update]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(def address-regex #"enode://[a-zA-Z0-9]+:?(.*)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def address-regex #"enode://[a-zA-Z0-9]+:?(.*)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
@ -17,11 +17,12 @@
:id (string/replace id "-" "") :id (string/replace id "-" "")
:name bootnode-name}) :name bootnode-name})
(defn fetch [id cofx] (fx/defn fetch [cofx id]
(let [network (get-in cofx [:db :network])] (let [network (get-in cofx [:db :network])]
(get-in cofx [:db :account/account :bootnodes network id]))) (get-in cofx [:db :account/account :bootnodes network id])))
(defn set-input [input-key value {:keys [db]}] (fx/defn set-input
[{:keys [db]} input-key value]
{:db (update {:db (update
db db
:bootnodes/manage :bootnodes/manage
@ -33,32 +34,32 @@
:name (string/blank? value) :name (string/blank? value)
:url (not (valid-address? value)))})}) :url (not (valid-address? value)))})})
(defn edit [id {:keys [db] :as cofx}] (fx/defn edit
[{:keys [db] :as cofx} id]
(let [{:keys [id (let [{:keys [id
address address
name]} (fetch id cofx) name]} (fetch cofx id)
fxs (handlers-macro/merge-fx fxs (fx/merge cofx
cofx (set-input :id id)
(set-input :id id) (set-input :url (str address))
(set-input :url (str address)) (set-input :name (str name)))]
(set-input :name (str name)))]
(assoc fxs :dispatch [:navigate-to :edit-bootnode]))) (assoc fxs :dispatch [:navigate-to :edit-bootnode])))
(defn custom-bootnodes-in-use? [{:keys [db] :as cofx}] (defn custom-bootnodes-in-use? [{:keys [db] :as cofx}]
(let [network (:network db)] (let [network (:network db)]
(get-in db [:account/account :settings :bootnodes network]))) (get-in db [:account/account :settings :bootnodes network])))
(defn delete [id {{:account/keys [account] :as db} :db :as cofx}] (fx/defn delete [{{:account/keys [account] :as db} :db :as cofx} id]
(let [network (:network db) (let [network (:network db)
new-account (update-in account [:bootnodes network] dissoc id)] new-account (update-in account [:bootnodes network] dissoc id)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :account/account new-account)} {:db (assoc db :account/account new-account)}
(accounts.update/account-update (accounts.update/account-update
(select-keys new-account [:bootnodes]) (select-keys new-account [:bootnodes])
(when (custom-bootnodes-in-use? cofx) {:success-event (when (custom-bootnodes-in-use? cofx)
[:accounts.update.callback/save-settings-success]))))) [:accounts.update.callback/save-settings-success])}))))
(defn upsert [{{:bootnodes/keys [manage] :account/keys [account] :as db} :db :as cofx}] (fx/defn upsert [{{:bootnodes/keys [manage] :account/keys [account] :as db} :db :as cofx}]
(let [{:keys [name (let [{:keys [name
id id
url]} manage url]} manage
@ -73,34 +74,36 @@
[network (:id bootnode)] [network (:id bootnode)]
bootnode)] bootnode)]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (dissoc db :bootnodes/manage)
{:db (dissoc db :bootnodes/manage) :dispatch [:navigate-back]}
:dispatch [:navigate-back]} (accounts.update/account-update
(accounts.update/account-update {:bootnodes new-bootnodes}
{:bootnodes new-bootnodes} {:success-event (when (custom-bootnodes-in-use? cofx)
(when (custom-bootnodes-in-use? cofx) [:accounts.update.callback/save-settings-success])}))))
[:accounts.update.callback/save-settings-success])))))
(defn toggle-custom-bootnodes [value {:keys [db] :as cofx}] (fx/defn toggle-custom-bootnodes
[{:keys [db] :as cofx} value]
(let [network (get-in db [:account/account :network]) (let [network (get-in db [:account/account :network])
settings (get-in db [:account/account :settings])] settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx (accounts.update/update-settings cofx
(accounts.update/update-settings (assoc-in settings [:bootnodes network] value)
(assoc-in settings [:bootnodes network] value) {:success-event [:accounts.update.callback/save-settings-success]})))
[:accounts.update.callback/save-settings-success]))))
(defn set-bootnodes-from-qr [url cofx] (fx/defn set-bootnodes-from-qr
[cofx url]
(assoc (set-input :url url cofx) (assoc (set-input :url url cofx)
:dispatch [:navigate-back])) :dispatch [:navigate-back]))
(defn show-delete-bootnode-confirmation [bootnode-id] (fx/defn show-delete-bootnode-confirmation
[_ bootnode-id]
{:ui/show-confirmation {:title (i18n/label :t/delete-bootnode-title) {:ui/show-confirmation {:title (i18n/label :t/delete-bootnode-title)
:content (i18n/label :t/delete-bootnode-are-you-sure) :content (i18n/label :t/delete-bootnode-are-you-sure)
:confirm-button-text (i18n/label :t/delete-bootnode) :confirm-button-text (i18n/label :t/delete-bootnode)
:on-accept #(re-frame/dispatch [:bootnodes.ui/delete-confirmed bootnode-id])}}) :on-accept #(re-frame/dispatch [:bootnodes.ui/delete-confirmed bootnode-id])}})
(defn delete-bootnode [bootnode-id cofx] (fx/defn delete-bootnode
(handlers-macro/merge-fx cofx [cofx bootnode-id]
(delete bootnode-id) (fx/merge cofx
(navigation/navigate-back))) (delete bootnode-id)
(navigation/navigate-back)))

View File

@ -14,7 +14,7 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.ens :as ens] [status-im.utils.ethereum.ens :as ens]
[status-im.utils.ethereum.resolver :as resolver] [status-im.utils.ethereum.resolver :as resolver]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.fx :as fx]
[status-im.utils.http :as http] [status-im.utils.http :as http]
[status-im.utils.multihash :as multihash] [status-im.utils.multihash :as multihash]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
@ -23,12 +23,12 @@
[status-im.utils.universal-links.core :as utils.universal-links] [status-im.utils.universal-links.core :as utils.universal-links]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
(defn initialize-browsers (fx/defn initialize-browsers
[{:keys [db all-stored-browsers]}] [{:keys [db all-stored-browsers]}]
(let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))] (let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))]
{:db (assoc db :browser/browsers browsers)})) {:db (assoc db :browser/browsers browsers)}))
(defn initialize-dapp-permissions (fx/defn initialize-dapp-permissions
[{:keys [db all-dapp-permissions]}] [{:keys [db all-dapp-permissions]}]
(let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))] (let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))]
{:db (assoc db :dapps/permissions dapp-permissions)})) {:db (assoc db :dapps/permissions dapp-permissions)}))
@ -42,7 +42,8 @@
(and (not error?) (and (not error?)
(string/starts-with? (get-current-url browser) "https://")))) (string/starts-with? (get-current-url browser) "https://"))))
(defn remove-browser [browser-id {:keys [db]}] (fx/defn remove-browser
[{:keys [db]} browser-id]
{:db (update-in db [:browser/browsers] dissoc browser-id) {:db (update-in db [:browser/browsers] dissoc browser-id)
:data-store/tx [(browser-store/remove-browser-tx browser-id)]}) :data-store/tx [(browser-store/remove-browser-tx browser-id)]})
@ -60,9 +61,9 @@
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))] (let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
(assoc browser :unsafe? (dependencies/phishing-detect history-host)))) (assoc browser :unsafe? (dependencies/phishing-detect history-host))))
(defn update-browser (fx/defn update-browser
[{:keys [browser-id history history-index error? dapp?] :as browser} [{:keys [db now]}
{:keys [db now]}] {:keys [browser-id history history-index error? dapp?] :as browser}]
(let [updated-browser (-> (assoc browser :timestamp now) (let [updated-browser (-> (assoc browser :timestamp now)
(check-if-dapp-in-list) (check-if-dapp-in-list)
(check-if-phishing-url))] (check-if-phishing-url))]
@ -77,24 +78,24 @@
(defn can-go-back? [{:keys [history-index]}] (defn can-go-back? [{:keys [history-index]}]
(pos? history-index)) (pos? history-index))
(defn navigate-to-previous-page (fx/defn navigate-to-previous-page
[cofx] [cofx]
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))] (let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
(when (can-go-back? browser) (when (can-go-back? browser)
(update-browser (assoc browser :history-index (dec history-index)) cofx)))) (update-browser cofx (assoc browser :history-index (dec history-index))))))
(defn can-go-forward? [{:keys [history-index history]}] (defn can-go-forward? [{:keys [history-index history]}]
(< history-index (dec (count history)))) (< history-index (dec (count history))))
(defn navigate-to-next-page (fx/defn navigate-to-next-page
[cofx] [cofx]
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))] (let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
(when (can-go-forward? browser) (when (can-go-forward? browser)
(update-browser (assoc browser :history-index (inc history-index)) cofx)))) (update-browser cofx (assoc browser :history-index (inc history-index))))))
(defn update-browser-history (fx/defn update-browser-history
;; TODO: not clear how this works ;; TODO: not clear how this works
[browser url loading? cofx] [cofx browser url loading?]
(when-not loading? (when-not loading?
(let [history-index (:history-index browser) (let [history-index (:history-index browser)
history (:history browser) history (:history browser)
@ -107,10 +108,10 @@
new-index (if slash? new-index (if slash?
history-index history-index
(dec (count new-history)))] (dec (count new-history)))]
(update-browser (assoc browser (update-browser cofx
(assoc browser
:history new-history :history new-history
:history-index new-index) :history-index new-index)))))))
cofx))))))
(defn ens? [host] (defn ens? [host]
(and (string? host) (and (string? host)
@ -122,20 +123,19 @@
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success hash]) (re-frame/dispatch [:browser.callback/resolve-ens-multihash-success hash])
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error])))) (re-frame/dispatch [:browser.callback/resolve-ens-multihash-error]))))
(defn resolve-ens-multihash-success (fx/defn resolve-ens-multihash-success
[hash {:keys [db] :as cofx}] [{:keys [db] :as cofx} hash]
(let [options (:browser/options db) (let [options (:browser/options db)
browsers (:browser/browsers db) browsers (:browser/browsers db)
browser (get browsers (:browser-id options)) browser (get browsers (:browser-id options))
history-index (:history-index browser)] history-index (:history-index browser)]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (assoc-in db [:browser/options :resolving?] false)}
{:db (assoc-in db [:browser/options :resolving?] false)} (update-browser (assoc-in browser [:history history-index]
(update-browser (assoc-in browser [:history history-index] (str "https://ipfs.infura.io/ipfs/" hash))))))
(str "https://ipfs.infura.io/ipfs/" hash))))))
(defn resolve-ens-multihash (fx/defn resolve-ens-multihash
[host loading? error? {{:keys [web3 network] :as db} :db}] [{{:keys [web3 network] :as db} :db} host loading? error?]
(when (and (not loading?) (when (and (not loading?)
(not error?) (not error?)
(ens? host)) (ens? host))
@ -148,86 +148,82 @@
:ens-name host :ens-name host
:cb resolve-ens-multihash-callback}}))) :cb resolve-ens-multihash-callback}})))
(defn update-browser-option (fx/defn update-browser-option
[option-key option-value {:keys [db]}] [{:keys [db]} option-key option-value]
{:db (assoc-in db [:browser/options option-key] option-value)}) {:db (assoc-in db [:browser/options option-key] option-value)})
(defn handle-browser-error [cofx] (fx/defn handle-browser-error
(handlers-macro/merge-fx cofx [cofx]
(update-browser-option :error? true) (fx/merge cofx
(update-browser-option :loading? false))) (update-browser-option :error? true)
(update-browser-option :loading? false)))
(defn update-browser-loading-option (fx/defn update-browser-on-nav-change
[loading? cofx] [cofx browser url loading? error?]
;; TODO(yenda) why are we doing this ?
(when platform/ios?
(update-browser-option :loading? loading? cofx)))
(defn update-browser-on-nav-change
[browser url loading? error? cofx]
(when (not= "about:blank" url) (when (not= "about:blank" url)
(let [host (http/url-host url)] (let [host (http/url-host url)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(resolve-ens-multihash host loading? error?) (resolve-ens-multihash host loading? error?)
(update-browser-history browser url loading?))))) (update-browser-history browser url loading?)))))
(defn navigation-state-changed [event error? cofx] (fx/defn navigation-state-changed
[cofx event error?]
(let [browser (get-current-browser (:db cofx)) (let [browser (get-current-browser (:db cofx))
{:strs [url loading]} (js->clj event)] {:strs [url loading]} (js->clj event)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(update-browser-loading-option loading) #(when platform/ios?
(update-browser-on-nav-change browser url loading error?)))) (update-browser-option % :loading? loading))
(update-browser-on-nav-change browser url loading error?))))
(defn open-url-in-current-browser (fx/defn open-url-in-current-browser
"Opens a url in the current browser, which mean no new entry is added to the home page "Opens a url in the current browser, which mean no new entry is added to the home page
and history of the current browser is updated so that the user can navigate back to the and history of the current browser is updated so that the user can navigate back to the
origin url" origin url"
;; TODO(yenda) is that desirable ? ;; TODO(yenda) is that desirable ?
[url cofx] [cofx url]
(let [browser (get-current-browser (:db cofx)) (let [browser (get-current-browser (:db cofx))
normalized-url (http/normalize-and-decode-url url) normalized-url (http/normalize-and-decode-url url)
host (http/url-host normalized-url)] host (http/url-host normalized-url)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(update-browser-option :url-editing? false) (update-browser-option :url-editing? false)
(resolve-ens-multihash host false false) (resolve-ens-multihash host false false)
(update-browser-history browser normalized-url false)))) (update-browser-history browser normalized-url false))))
(defn navigate-to-browser (fx/defn navigate-to-browser
[{{:keys [view-id]} :db :as cofx}] [{{:keys [view-id]} :db :as cofx}]
(if (= view-id :dapp-description) (if (= view-id :dapp-description)
(navigation/navigate-reset (navigation/navigate-reset cofx
{:index 1 {:index 1
:actions [{:routeName :home} :actions [{:routeName :home}
{:routeName :browser}]} {:routeName :browser}]})
cofx) (navigation/navigate-to-cofx cofx :browser nil)))
(navigation/navigate-to-cofx :browser nil cofx)))
(defn open-url (fx/defn open-url
"Opens a url in the browser. If a host can be extracted from the url and "Opens a url in the browser. If a host can be extracted from the url and
there is already a browser for this host, this browser is reused there is already a browser for this host, this browser is reused
If the browser is reused, the history is flushed" If the browser is reused, the history is flushed"
[url {:keys [db] :as cofx}] [{:keys [db] :as cofx} url]
(let [normalized-url (http/normalize-and-decode-url url) (let [normalized-url (http/normalize-and-decode-url url)
host (http/url-host normalized-url) host (http/url-host normalized-url)
browser {:browser-id (or host (random/id)) browser {:browser-id (or host (random/id))
:history-index 0 :history-index 0
:history [normalized-url]}] :history [normalized-url]}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :browser/options {:db (assoc db :browser/options
{:browser-id (:browser-id browser)})} {:browser-id (:browser-id browser)})}
(navigate-to-browser) (navigate-to-browser)
(update-browser browser) (update-browser browser)
(resolve-ens-multihash host false false)))) (resolve-ens-multihash host false false))))
(defn open-existing-browser (fx/defn open-existing-browser
"Opens an existing browser with it's history" "Opens an existing browser with it's history"
[browser-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} browser-id]
(let [browser (get-in db [:browser/browsers browser-id])] (let [browser (get-in db [:browser/browsers browser-id])]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :browser/options {:db (assoc db :browser/options
{:browser-id browser-id})} {:browser-id browser-id})}
(update-browser browser) (update-browser browser)
(navigation/navigate-to-cofx :browser nil)))) (navigation/navigate-to-cofx :browser nil))))
(defn web3-send-async (defn web3-send-async
[{:keys [method] :as payload} message-id {:keys [db]}] [{:keys [method] :as payload} message-id {:keys [db]}]
@ -243,7 +239,8 @@
:error %1 :error %1
:result %2}])]})) :result %2}])]}))
(defn send-to-bridge [message cofx] (fx/defn send-to-bridge
[cofx message]
{:browser/send-to-bridge {:message message {:browser/send-to-bridge {:message message
:webview (get-in cofx [:db :webview-bridge])}}) :webview (get-in cofx [:db :webview-bridge])}})
@ -259,14 +256,14 @@
cofx) cofx)
(web3-send-async payload message-id cofx)))) (web3-send-async payload message-id cofx))))
(defn handle-scanned-qr-code (fx/defn handle-scanned-qr-code
[data message cofx] [cofx data message]
(handlers-macro/merge-fx cofx (fx/merge cofx
(send-to-bridge (assoc message :result data)) (send-to-bridge (assoc message :result data))
(navigation/navigate-back))) (navigation/navigate-back)))
(defn process-bridge-message (fx/defn process-bridge-message
[message {:keys [db] :as cofx}] [{:keys [db] :as cofx} message]
(let [{:browser/keys [options browsers]} db (let [{:browser/keys [options browsers]} db
{:keys [browser-id]} options {:keys [browser-id]} options
browser (get browsers browser-id) browser (get browsers browser-id)
@ -287,18 +284,19 @@
(web3-send-async-read-only dapp-name payload messageId cofx) (web3-send-async-read-only dapp-name payload messageId cofx)
(= type constants/scan-qr-code) (= type constants/scan-qr-code)
(qr-scanner/scan-qr-code {:modal? false} (qr-scanner/scan-qr-code cofx
{:modal? false}
(merge {:handler :browser.bridge.callback/qr-code-scanned} (merge {:handler :browser.bridge.callback/qr-code-scanned}
{:type constants/scan-qr-code-callback {:type constants/scan-qr-code-callback
:data data}) :data data}))
cofx)
(= type constants/status-api-request) (= type constants/status-api-request)
(browser.permissions/process-permissions dapp-name permissions cofx)))) (browser.permissions/process-permissions cofx dapp-name permissions))))
(defn handle-message-link [link cofx] (fx/defn handle-message-link
[cofx link]
(if (utils.universal-links/universal-link? link) (if (utils.universal-links/universal-link? link)
(utils.universal-links/handle-url link cofx) (utils.universal-links/handle-url cofx link)
{:browser/show-browser-selection link})) {:browser/show-browser-selection link}))
(defn filter-letters-numbers-and-replace-dot-on-dash [value] (defn filter-letters-numbers-and-replace-dot-on-dash [value]
@ -310,7 +308,8 @@
(= cc 46) (= cc 46)
"-"))) "-")))
(defn open-chat-from-browser [host cofx] (fx/defn open-chat-from-browser
[cofx host]
(let [topic (string/lower-case (apply str (map filter-letters-numbers-and-replace-dot-on-dash host)))] (let [topic (string/lower-case (apply str (map filter-letters-numbers-and-replace-dot-on-dash host)))]
{:dispatch [:create-new-public-chat topic true]})) {:dispatch [:create-new-public-chat topic true]}))

View File

@ -4,7 +4,7 @@
[status-im.data-store.dapp-permissions :as dapp-permissions] [status-im.data-store.dapp-permissions :as dapp-permissions]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(def supported-permissions (def supported-permissions
{constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile) {constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
@ -36,7 +36,7 @@
(:address account))} (:address account))}
(vec allowed-permissions)))) (vec allowed-permissions))))
(defn send-permissions-data-to-bridge (fx/defn send-permissions-data-to-bridge
"If there is granted permissions, return the data to the bridge "If there is granted permissions, return the data to the bridge
If no permission were granted and dapp requested web3 permission, If no permission were granted and dapp requested web3 permission,
return `web3-permission-request-denied` message type return `web3-permission-request-denied` message type
@ -66,8 +66,8 @@
:else :else
{:db new-db}))) {:db new-db})))
(defn update-dapp-permissions (fx/defn update-dapp-permissions
[dapp-name {:keys [db]}] [{:keys [db]} dapp-name]
(let [allowed-permissions-set (get-allowed-permissions db) (let [allowed-permissions-set (get-allowed-permissions db)
allowed-permissions {:dapp dapp-name allowed-permissions {:dapp dapp-name
:permissions (vec allowed-permissions-set)}] :permissions (vec allowed-permissions-set)}]
@ -75,12 +75,12 @@
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions) {:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
:data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]}))) :data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]})))
(defn process-next-permission (fx/defn process-next-permission
"Process next permission by removing it from pending permissions "Process next permission by removing it from pending permissions
and prompting user and prompting user
if there is no pending permissions left, save all granted permissions if there is no pending permissions left, save all granted permissions
and return the result to the bridge" and return the result to the bridge"
[dapp-name {:keys [db] :as cofx}] [{:keys [db] :as cofx} dapp-name]
(let [pending-permissions (get-pending-permissions db) (let [pending-permissions (get-pending-permissions db)
next-permission (first pending-permissions)] next-permission (first pending-permissions)]
(if next-permission (if next-permission
@ -89,24 +89,24 @@
(assoc-in [:browser/options :show-permission] (assoc-in [:browser/options :show-permission]
{:requested-permission next-permission {:requested-permission next-permission
:dapp-name dapp-name}))} :dapp-name dapp-name}))}
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:browser/options :show-permission] nil)} {:db (assoc-in db [:browser/options :show-permission] nil)}
(update-dapp-permissions dapp-name) (update-dapp-permissions dapp-name)
(send-permissions-data-to-bridge))))) (send-permissions-data-to-bridge)))))
(defn allow-permission (fx/defn allow-permission
"Add permission to set of allowed permission and process next permission" "Add permission to set of allowed permission and process next permission"
[dapp-name permission {:keys [db] :as cofx}] [{:keys [db] :as cofx} dapp-name permission]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (add-allowed-permission db permission)} {:db (add-allowed-permission db permission)}
(process-next-permission dapp-name))) (process-next-permission dapp-name)))
(defn process-permissions (fx/defn process-permissions
"Process the permissions requested by a dapp "Process the permissions requested by a dapp
If all supported permissions are already granted, return the result immediatly If all supported permissions are already granted, return the result immediatly
to the bridge to the bridge
Otherwise process the first permission which will prompt user" Otherwise process the first permission which will prompt user"
[dapp-name requested-permissions cofx] [cofx dapp-name requested-permissions]
(let [requested-permissions-set (set requested-permissions) (let [requested-permissions-set (set requested-permissions)
current-dapp-permissions (get-in cofx [:db :dapps/permissions dapp-name :permissions]) current-dapp-permissions (get-in cofx [:db :dapps/permissions dapp-name :permissions])
current-dapp-permissions-set (set current-dapp-permissions) current-dapp-permissions-set (set current-dapp-permissions)
@ -122,4 +122,4 @@
:requested-permissions requested-permissions-set})] :requested-permissions requested-permissions-set})]
(if (empty? pending-permissions) (if (empty? pending-permissions)
(send-permissions-data-to-bridge new-cofx) (send-permissions-data-to-bridge new-cofx)
(process-next-permission dapp-name new-cofx)))) (process-next-permission new-cofx dapp-name))))

View File

@ -6,7 +6,8 @@
[status-im.chat.constants :as chat-constants] [status-im.chat.constants :as chat-constants]
[status-im.chat.commands.protocol :as protocol] [status-im.chat.commands.protocol :as protocol]
[status-im.chat.commands.impl.transactions :as transactions] [status-im.chat.commands.impl.transactions :as transactions]
[status-im.utils.handlers :as handlers])) [status-im.utils.handlers :as handlers]
[status-im.utils.fx :as fx]))
(def register (def register
"Register of all commands. Whenever implementing a new command, "Register of all commands. Whenever implementing a new command,
@ -101,10 +102,10 @@
{:id->command id->command {:id->command id->command
:access-scope->command-id access-scope->command-id})) :access-scope->command-id access-scope->command-id}))
(defn load-commands (fx/defn load-commands
"Takes collection of things implementing the command protocol and db, "Takes collection of things implementing the command protocol and db,
correctly indexes them and adds them to db in a way that preserves existing commands" correctly indexes them and adds them to db in a way that preserves existing commands"
[commands {:keys [db]}] [{:keys [db]} commands]
(let [{:keys [id->command access-scope->command-id]} (index-commands commands)] (let [{:keys [id->command access-scope->command-id]} (index-commands commands)]
{:db (-> db {:db (-> db
(update :id->command merge id->command) (update :id->command merge id->command)

View File

@ -1,6 +1,5 @@
(ns status-im.chat.commands.impl.transactions (ns status-im.chat.commands.impl.transactions
(:require-macros [status-im.utils.views :refer [defview letsubs]] (:require-macros [status-im.utils.views :refer [defview letsubs]])
[status-im.utils.handlers-macro :as handlers-macro])
(:require [clojure.string :as string] (:require [clojure.string :as string]
[reagent.core :as reagent] [reagent.core :as reagent]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
@ -19,6 +18,7 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.datetime :as datetime] [status-im.utils.datetime :as datetime]
[status-im.utils.fx :as fx]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.ui.screens.wallet.db :as wallet.db] [status-im.ui.screens.wallet.db :as wallet.db]
[status-im.ui.screens.wallet.choose-recipient.events :as choose-recipient.events] [status-im.ui.screens.wallet.choose-recipient.events :as choose-recipient.events]
@ -302,25 +302,24 @@
next-view-id (if (:wallet-set-up-passed? sender-account) next-view-id (if (:wallet-set-up-passed? sender-account)
:wallet-send-transaction-modal :wallet-send-transaction-modal
:wallet-onboarding-setup)] :wallet-onboarding-setup)]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (-> db
{:db (-> db (update-in [:wallet :send-transaction]
(update-in [:wallet :send-transaction] assoc
assoc :amount (money/formatted->internal value symbol decimals)
:amount (money/formatted->internal value symbol decimals) :amount-text amount
:amount-text amount :amount-error error)
:amount-error error) (choose-recipient.events/fill-request-details
(choose-recipient.events/fill-request-details (transaction-details recipient-contact symbol))
(transaction-details recipient-contact symbol)) (update-in [:wallet :send-transaction]
(update-in [:wallet :send-transaction] dissoc :id :password :wrong-password?))
dissoc :id :password :wrong-password?)) ;; TODO(janherich) - refactor wallet send events, updating gas price
;; TODO(janherich) - refactor wallet send events, updating gas price ;; is generic thing which shouldn't be defined in wallet.send, then
;; is generic thing which shouldn't be defined in wallet.send, then ;; we can include the utility helper without running into circ-dep problem
;; we can include the utility helper without running into circ-dep problem :update-gas-price {:web3 (:web3 db)
:update-gas-price {:web3 (:web3 db) :success-event :wallet/update-gas-price-success
:success-event :wallet/update-gas-price-success :edit? false}}
:edit? false}} (navigation/navigate-to-cofx next-view-id {}))))
(navigation/navigate-to-cofx next-view-id {}))))
protocol/EnhancedParameters protocol/EnhancedParameters
(enhance-send-parameters [_ parameters cofx] (enhance-send-parameters [_ parameters cofx]
(-> (inject-network-info parameters cofx) (-> (inject-network-info parameters cofx)

View File

@ -3,7 +3,8 @@
[status-im.chat.commands.core :as commands] [status-im.chat.commands.core :as commands]
[status-im.chat.constants :as chat-constants] [status-im.chat.constants :as chat-constants]
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.chat.models.input :as input-model])) [status-im.chat.models.input :as input-model]
[status-im.utils.fx :as fx]))
(defn- current-param-position [input-text selection] (defn- current-param-position [input-text selection]
(when selection (when selection
@ -25,10 +26,10 @@
(> input-params-count params-count) :more-than-needed))) (> input-params-count params-count) :more-than-needed)))
(defn selected-chat-command (defn selected-chat-command
"Takes input text, text-selection and `protocol/id->command-props` map (result of "Takes input text, text-selection and `protocol/id->command-props` map (result of
the `chat-commands` fn) and returns the corresponding `command-props` entry, the `chat-commands` fn) and returns the corresponding `command-props` entry,
or nothing if input text doesn't match any available command. or nothing if input text doesn't match any available command.
Besides keys `:params` and `:type`, the returned map contains: Besides keys `:params` and `:type`, the returned map contains:
* `:input-params` - parsed parameters from the input text as map of `param-id->entered-value` * `:input-params` - parsed parameters from the input text as map of `param-id->entered-value`
# `:current-param-position` - index of the parameter the user is currently focused on (cursor position # `:current-param-position` - index of the parameter the user is currently focused on (cursor position
in relation to parameters), could be nil if the input is not selected in relation to parameters), could be nil if the input is not selected
@ -50,9 +51,9 @@
:current-param-position (current-param-position input-text text-selection) :current-param-position (current-param-position input-text text-selection)
:command-completion (command-completion input-params params))))))) :command-completion (command-completion input-params params)))))))
(defn set-command-parameter (fx/defn set-command-parameter
"Set value as command parameter for the current chat" "Set value as command parameter for the current chat"
[last-param? param-index value {:keys [db]}] [{:keys [db]} last-param? param-index value]
(let [{:keys [current-chat-id chats]} db (let [{:keys [current-chat-id chats]} db
[command & params] (-> (get-in chats [current-chat-id :input-text]) [command & params] (-> (get-in chats [current-chat-id :input-text])
input-model/split-command-args) input-model/split-command-args)
@ -73,9 +74,9 @@
(chat-model/set-chat-ui-props {:validation-messages nil}) (chat-model/set-chat-ui-props {:validation-messages nil})
(assoc-in [:chats current-chat-id :input-text] input-text))})) (assoc-in [:chats current-chat-id :input-text] input-text))}))
(defn select-chat-input-command (fx/defn select-chat-input-command
"Takes command and (optional) map of input-parameters map and sets it as current-chat input" "Takes command and (optional) map of input-parameters map and sets it as current-chat input"
[{:keys [type params]} input-params {:keys [db]}] [{:keys [db]} {:keys [type params]} input-params]
(let [{:keys [current-chat-id chat-ui-props]} db] (let [{:keys [current-chat-id chat-ui-props]} db]
{:db (-> db {:db (-> db
(chat-model/set-chat-ui-props {:show-suggestions? false (chat-model/set-chat-ui-props {:show-suggestions? false

View File

@ -11,15 +11,15 @@
"Scope of the command, defined as set of values representing contexts "Scope of the command, defined as set of values representing contexts
where in which command is available, together with `id` it forms unique where in which command is available, together with `id` it forms unique
identifier for each command. identifier for each command.
Available values for the set are: Available values for the set are:
`id-of-the-any-chat` - command if available only for the specified chat `id-of-the-any-chat` - command if available only for the specified chat
`:personal-chats` - command is available for any personal 1-1 chat `:personal-chats` - command is available for any personal 1-1 chat
`:group-chats` - command is available for any group chat `:group-chats` - command is available for any group chat
`:public-chats` - command is available for any public chat ") `:public-chats` - command is available for any public chat ")
(description [this] "Description of the command") (description [this] "Description of the command")
(parameters [this] (parameters [this]
"Ordered sequence of command parameter templates, where each parameter "Ordered sequence of command parameter templates, where each parameter
is defined as map consisting of mandatory `:id`, `:title` and `:type` keys, is defined as map consisting of mandatory `:id`, `:title` and `:type` keys,
and optional `:suggestions` field. and optional `:suggestions` field.
When used, `:suggestions` containes reference to any generic helper component When used, `:suggestions` containes reference to any generic helper component
rendering suggestions for the argument (input code will handle when and where rendering suggestions for the argument (input code will handle when and where
@ -30,7 +30,7 @@
found and command send workflow can proceed, or one/more errors to display. found and command send workflow can proceed, or one/more errors to display.
Each error is represented by the map containing `:title` and `:description` keys.") Each error is represented by the map containing `:title` and `:description` keys.")
(on-send [this command-message cofx] (on-send [this command-message cofx]
"Function which can provide any extra effects to be produced in addition to "Function which can provide any extra effects to be produced in addition to
normal message effects which happen whenever message is sent") normal message effects which happen whenever message is sent")
(on-receive [this command-message cofx] (on-receive [this command-message cofx]
"Function which can provide any extre effects to be produced in addition to "Function which can provide any extre effects to be produced in addition to

View File

@ -1,5 +1,6 @@
(ns status-im.chat.commands.receiving (ns status-im.chat.commands.receiving
(:require [status-im.chat.commands.protocol :as protocol])) (:require [status-im.chat.commands.protocol :as protocol]
[status-im.utils.fx :as fx]))
;; TODO(janherich) remove after couple of releases when danger of messages ;; TODO(janherich) remove after couple of releases when danger of messages
;; with old command references will be low ;; with old command references will be low
@ -16,10 +17,10 @@
(or (get id->command path) (or (get id->command path)
(get id->command (get old->new-path path))))) (get id->command (get old->new-path path)))))
(defn receive (fx/defn receive
"Performs receive effects for command message. Does nothing "Performs receive effects for command message. Does nothing
when message is not of the command type or command can't be found." when message is not of the command type or command can't be found."
[message {:keys [db] :as cofx}] [{:keys [db] :as cofx} message]
(let [id->command (:id->command db)] (let [id->command (:id->command db)]
(when-let [{:keys [type]} (lookup-command-by-ref message id->command)] (when-let [{:keys [type]} (lookup-command-by-ref message id->command)]
(protocol/on-receive type message cofx)))) (protocol/on-receive type message cofx))))

View File

@ -6,7 +6,7 @@
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.chat.models.input :as input-model] [status-im.chat.models.input :as input-model]
[status-im.chat.models.message :as message-model] [status-im.chat.models.message :as message-model]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
;; TODO(janherich) remove after couple of releases when danger of messages ;; TODO(janherich) remove after couple of releases when danger of messages
;; with old command references will be low ;; with old command references will be low
@ -43,9 +43,9 @@
:params (or new-parameter-map parameter-map)} :params (or new-parameter-map parameter-map)}
content)})) content)}))
(defn validate-and-send (fx/defn validate-and-send
"Validates and sends command in current chat" "Validates and sends command in current chat"
[input-text {:keys [type params] :as command} {:keys [db now random-id] :as cofx}] [{:keys [db now random-id] :as cofx} input-text {:keys [type params] :as command}]
(let [chat-id (:current-chat-id db) (let [chat-id (:current-chat-id db)
parameter-map (commands-input/parse-parameters params input-text)] parameter-map (commands-input/parse-parameters params input-text)]
(if-let [validation-error (protocol/validate type parameter-map cofx)] (if-let [validation-error (protocol/validate type parameter-map cofx)]
@ -53,28 +53,28 @@
{:db (chat-model/set-chat-ui-props db {:validation-messages validation-error {:db (chat-model/set-chat-ui-props db {:validation-messages validation-error
:sending-in-progress? false})} :sending-in-progress? false})}
;; no errors, define clean-up effects which will have to be performed in all cases ;; no errors, define clean-up effects which will have to be performed in all cases
(let [cleanup-fx (handlers-macro/merge-fx cofx (let [cleanup-fx (fx/merge cofx
{:db (chat-model/set-chat-ui-props {:db (chat-model/set-chat-ui-props
db {:sending-in-progress? false})} db {:sending-in-progress? false})}
(input-model/set-chat-input-text nil))] (input-model/set-chat-input-text nil))]
(if (satisfies? protocol/Yielding type) (if (satisfies? protocol/Yielding type)
;; yield control implemented, don't send the message ;; yield control implemented, don't send the message
(handlers-macro/merge-fx cofx (fx/merge cofx
cleanup-fx cleanup-fx
(protocol/yield-control type parameter-map)) #(protocol/yield-control type parameter-map %))
;; no yield control, proceed with sending the command message ;; no yield control, proceed with sending the command message
(let [command-message (create-command-message chat-id type parameter-map cofx)] (let [command-message (create-command-message chat-id type parameter-map cofx)]
(handlers-macro/merge-fx cofx (fx/merge cofx
cleanup-fx cleanup-fx
(protocol/on-send type command-message) #(protocol/on-send type command-message %)
(input-model/set-chat-input-metadata nil) (input-model/set-chat-input-metadata nil)
(message-model/send-message command-message)))))))) (message-model/send-message command-message))))))))
(defn send (fx/defn send
"Sends command with given parameters in particular chat" "Sends command with given parameters in particular chat"
[chat-id {:keys [type]} parameter-map cofx] [cofx chat-id {:keys [type]} parameter-map]
(let [command-message (create-command-message chat-id type parameter-map cofx)] (let [command-message (create-command-message chat-id type parameter-map cofx)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(protocol/on-send type command-message) #(protocol/on-send type command-message %)
(input-model/set-chat-input-metadata nil) (input-model/set-chat-input-metadata nil)
(message-model/send-message command-message)))) (message-model/send-message command-message))))

View File

@ -1,25 +1,25 @@
(ns status-im.chat.core (ns status-im.chat.core
(:require [status-im.data-store.user-statuses :as user-statuses-store])) (:require [status-im.data-store.user-statuses :as user-statuses-store]
[status-im.utils.fx :as fx]))
;; Seen messages ;; Seen messages
(defn receive-seen (fx/defn receive-seen
[chat-id sender {:keys [message-ids]} {:keys [db js-obj]}] [{:keys [db js-obj]} chat-id sender {:keys [message-ids]}]
(merge (merge {:confirm-messages-processed [{:web3 (:web3 db)
{:confirm-messages-processed [{:web3 (:web3 db) :js-obj js-obj}]}
:js-obj js-obj}]} (when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages]) (select-keys message-ids)
(select-keys message-ids) keys)]
keys)] (let [statuses (map (fn [message-id]
(let [statuses (map (fn [message-id] {:chat-id chat-id
{:chat-id chat-id :message-id message-id
:message-id message-id :whisper-identity sender
:whisper-identity sender :status :seen})
:status :seen}) seen-messages-ids)]
seen-messages-ids)] {:db (reduce (fn [acc {:keys [message-id] :as status}]
{:db (reduce (fn [acc {:keys [message-id] :as status}] (assoc-in acc [:chats chat-id :message-statuses
(assoc-in acc [:chats chat-id :message-statuses message-id sender]
message-id sender] status))
status)) db
db statuses)
statuses) :data-store/tx [(user-statuses-store/save-statuses-tx statuses)]}))))
:data-store/tx [(user-statuses-store/save-statuses-tx statuses)]}))))

View File

@ -7,15 +7,14 @@
[status-im.chat.models :as models] [status-im.chat.models :as models]
[status-im.chat.models.loading :as chat-loading] [status-im.chat.models.loading :as chat-loading]
[status-im.chat.models.message :as models.message] [status-im.chat.models.message :as models.message]
[status-im.constants :as constants]
[status-im.data-store.user-statuses :as user-statuses-store] [status-im.data-store.user-statuses :as user-statuses-store]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.transport.message.core :as transport.message] [status-im.transport.message.core :as transport.message]
[status-im.transport.message.v1.group-chat :as group-chat] [status-im.transport.message.v1.group-chat :as group-chat]
[status-im.transport.message.v1.public-chat :as public-chat] [status-im.transport.message.v1.public-chat :as public-chat]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]))
;;;; Effects ;;;; Effects
@ -67,7 +66,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-to-chat :navigate-to-chat
(fn [cofx [_ chat-id opts]] (fn [cofx [_ chat-id opts]]
(models/navigate-to-chat chat-id opts cofx))) (models/navigate-to-chat cofx chat-id opts)))
(handlers/register-handler-fx (handlers/register-handler-fx
:load-more-messages :load-more-messages
@ -82,9 +81,9 @@
(models/start-chat contact-id opts cofx))) (models/start-chat contact-id opts cofx)))
(defn remove-chat-and-navigate-home [cofx [_ chat-id]] (defn remove-chat-and-navigate-home [cofx [_ chat-id]]
(handlers-macro/merge-fx cofx (fx/merge cofx
(models/remove-chat chat-id) (models/remove-chat chat-id)
(navigation/replace-view :home))) (navigation/replace-view :home)))
(handlers/register-handler-fx (handlers/register-handler-fx
:remove-chat-and-navigate-home :remove-chat-and-navigate-home
@ -111,17 +110,17 @@
:confirm-button-text (i18n/label :t/clear) :confirm-button-text (i18n/label :t/clear)
:on-accept #(re-frame/dispatch [:clear-history])}})) :on-accept #(re-frame/dispatch [:clear-history])}}))
(defn create-new-public-chat [topic modal? cofx] (fx/defn create-new-public-chat [cofx topic modal?]
(handlers-macro/merge-fx cofx (fx/merge cofx
(models/add-public-chat topic) (models/add-public-chat topic)
(models/navigate-to-chat topic {:modal? modal? (models/navigate-to-chat topic {:modal? modal?
:navigation-replace? true}) :navigation-replace? true})
(public-chat/join-public-chat topic))) (public-chat/join-public-chat topic)))
(handlers/register-handler-fx (handlers/register-handler-fx
:create-new-public-chat :create-new-public-chat
(fn [cofx [_ topic modal?]] (fn [cofx [_ topic modal?]]
(create-new-public-chat topic modal? cofx))) (create-new-public-chat cofx topic modal?)))
(defn- group-name-from-contacts [selected-contacts all-contacts username] (defn- group-name-from-contacts [selected-contacts all-contacts username]
(->> selected-contacts (->> selected-contacts
@ -139,31 +138,30 @@
(group-name-from-contacts selected-contacts (group-name-from-contacts selected-contacts
(:contacts/contacts db) (:contacts/contacts db)
(:username db)))] (:username db)))]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (assoc db :group/selected-contacts #{})}
{:db (assoc db :group/selected-contacts #{})} (models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts) (navigation/navigate-to-cofx :home nil)
(navigation/navigate-to-cofx :home nil) (models/navigate-to-chat random-id {})
(models/navigate-to-chat random-id {}) #(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id %)))))
(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
(defn show-profile [identity {:keys [db]}] (fx/defn show-profile [{:keys [db]} identity]
(navigation/navigate-to-cofx :profile nil {:db (assoc db :contacts/identity identity)})) (navigation/navigate-to-cofx {:db (assoc db :contacts/identity identity)} :profile nil))
(handlers/register-handler-fx (handlers/register-handler-fx
:show-profile :show-profile
(fn [cofx [_ identity]] (fn [cofx [_ identity]]
(show-profile identity cofx))) (show-profile cofx identity)))
(handlers/register-handler-fx (handlers/register-handler-fx
:resend-message :resend-message
(fn [cofx [_ chat-id message-id]] (fn [cofx [_ chat-id message-id]]
(models.message/resend-message chat-id message-id cofx))) (models.message/resend-message cofx chat-id message-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:delete-message :delete-message
(fn [cofx [_ chat-id message-id]] (fn [cofx [_ chat-id message-id]]
(models.message/delete-message chat-id message-id cofx))) (models.message/delete-message cofx chat-id message-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:disable-cooldown :disable-cooldown

View File

@ -12,7 +12,7 @@
[status-im.chat.commands.sending :as commands-sending] [status-im.chat.commands.sending :as commands-sending]
[status-im.ui.components.react :as react-comp] [status-im.ui.components.react :as react-comp]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
;;;; Effects ;;;; Effects
@ -44,9 +44,9 @@
;;;; Helper functions ;;;; Helper functions
(defn chat-input-focus (fx/defn chat-input-focus
"Returns fx for focusing on active chat input reference" "Returns fx for focusing on active chat input reference"
[ref {{:keys [current-chat-id chat-ui-props]} :db}] [{{:keys [current-chat-id chat-ui-props]} :db} ref]
(when-let [cmp-ref (get-in chat-ui-props [current-chat-id ref])] (when-let [cmp-ref (get-in chat-ui-props [current-chat-id ref])]
{::focus-rn-component cmp-ref})) {::focus-rn-component cmp-ref}))
@ -55,25 +55,25 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:set-chat-input-text :set-chat-input-text
(fn [cofx [_ text]] (fn [cofx [_ text]]
(input-model/set-chat-input-text text cofx))) (input-model/set-chat-input-text cofx text)))
(handlers/register-handler-fx (handlers/register-handler-fx
:select-chat-input-command :select-chat-input-command
(fn [{:keys [db] :as cofx} [_ command params metadata]] (fn [{:keys [db] :as cofx} [_ command params metadata]]
(handlers-macro/merge-fx cofx (fx/merge cofx
(input-model/set-chat-input-metadata metadata) (input-model/set-chat-input-metadata metadata)
(commands-input/select-chat-input-command command params) (commands-input/select-chat-input-command command params)
(chat-input-focus :input-ref)))) (chat-input-focus :input-ref))))
(handlers/register-handler-fx (handlers/register-handler-fx
:set-command-parameter :set-command-parameter
(fn [cofx [_ last-param? index value]] (fn [cofx [_ last-param? index value]]
(commands-input/set-command-parameter last-param? index value cofx))) (commands-input/set-command-parameter cofx last-param? index value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:chat-input-focus :chat-input-focus
(fn [cofx [_ ref]] (fn [cofx [_ ref]]
(chat-input-focus ref cofx))) (chat-input-focus cofx ref)))
(handlers/register-handler-fx (handlers/register-handler-fx
:chat-input-blur :chat-input-blur
@ -84,10 +84,9 @@
(defn command-complete-fx (defn command-complete-fx
"command is complete, set `:sending-in-progress?` flag and proceed with command processing" "command is complete, set `:sending-in-progress?` flag and proceed with command processing"
[input-text command {:keys [db now random-id] :as cofx}] [input-text command {:keys [db now random-id] :as cofx}]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (model/set-chat-ui-props db {:sending-in-progress? true})}
{:db (model/set-chat-ui-props db {:sending-in-progress? true})} (commands-sending/validate-and-send input-text command)))
(commands-sending/validate-and-send input-text command)))
(defn command-not-complete-fx (defn command-not-complete-fx
"command is not complete, just add space after command if necessary" "command is not complete, just add space after command if necessary"
@ -101,13 +100,12 @@
"no command detected, when not empty, proceed by sending text message without command processing" "no command detected, when not empty, proceed by sending text message without command processing"
[input-text current-chat-id {:keys [db] :as cofx}] [input-text current-chat-id {:keys [db] :as cofx}]
(when-not (string/blank? input-text) (when-not (string/blank? input-text)
(handlers-macro/merge-fx (fx/merge cofx
cofx (input-model/set-chat-input-text nil)
(input-model/set-chat-input-text nil) (input-model/set-chat-input-metadata nil)
(input-model/set-chat-input-metadata nil) (message-model/send-message {:chat-id current-chat-id
(message-model/send-message {:chat-id current-chat-id :content-type constants/text-content-type
:content-type constants/text-content-type :content input-text}))))
:content input-text}))))
(handlers/register-handler-fx (handlers/register-handler-fx
:send-current-message :send-current-message

View File

@ -3,7 +3,6 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.chat.models.message :as message-model] [status-im.chat.models.message :as message-model]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.models.transactions :as wallet.transactions])) [status-im.models.transactions :as wallet.transactions]))
;;;; Handlers ;;;; Handlers
@ -13,7 +12,7 @@
(fn [messages] (fn [messages]
(re-frame/dispatch [:chat-received-message/add messages]))) (re-frame/dispatch [:chat-received-message/add messages])))
(defn- filter-messages [messages cofx] (defn- filter-messages [cofx messages]
(:accumulated (reduce (fn [{:keys [seen-ids] :as acc} (:accumulated (reduce (fn [{:keys [seen-ids] :as acc}
{:keys [message-id] :as message}] {:keys [message-id] :as message}]
(if (and (message-model/add-to-chat? cofx message) (if (and (message-model/add-to-chat? cofx message)
@ -30,4 +29,4 @@
:chat-received-message/add :chat-received-message/add
message-model/receive-interceptors message-model/receive-interceptors
(fn [cofx [_ messages]] (fn [cofx [_ messages]]
(message-model/receive-many (filter-messages messages cofx) cofx))) (message-model/receive-many cofx (filter-messages cofx messages))))

View File

@ -11,13 +11,13 @@
[status-im.utils.clocks :as utils.clocks] [status-im.utils.clocks :as utils.clocks]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn multi-user-chat? [chat-id cofx] (defn multi-user-chat? [cofx chat-id]
(get-in cofx [:db :chats chat-id :group-chat])) (get-in cofx [:db :chats chat-id :group-chat]))
(defn group-chat? [chat-id cofx] (defn group-chat? [cofx chat-id]
(and (multi-user-chat? chat-id cofx) (and (multi-user-chat? cofx chat-id)
(not (get-in cofx [:db :chats chat-id :public?])))) (not (get-in cofx [:db :chats chat-id :public?]))))
(defn public-chat? [chat-id cofx] (defn public-chat? [chat-id cofx]
@ -45,9 +45,9 @@
:contacts [chat-id] :contacts [chat-id]
:last-clock-value 0})) :last-clock-value 0}))
(defn upsert-chat (fx/defn upsert-chat
"Upsert chat when not deleted" "Upsert chat when not deleted"
[{:keys [chat-id] :as chat-props} {:keys [db] :as cofx}] [{:keys [db] :as cofx} {:keys [chat-id] :as chat-props}]
(let [chat (merge (let [chat (merge
(or (get (:chats db) chat-id) (or (get (:chats db) chat-id)
(create-new-chat chat-id cofx)) (create-new-chat chat-id cofx))
@ -59,29 +59,31 @@
;; when chat is deleted, don't change anything ;; when chat is deleted, don't change anything
{:db db}))) {:db db})))
(defn add-public-chat (fx/defn add-public-chat
"Adds new public group chat to db & realm" "Adds new public group chat to db & realm"
[topic cofx] [cofx topic]
(upsert-chat {:chat-id topic (upsert-chat cofx
{:chat-id topic
:is-active true :is-active true
:name topic :name topic
:group-chat true :group-chat true
:contacts [] :contacts []
:public? true} cofx)) :public? true}))
(defn add-group-chat (fx/defn add-group-chat
"Adds new private group chat to db & realm" "Adds new private group chat to db & realm"
[chat-id chat-name admin participants cofx] [cofx chat-id chat-name admin participants]
(upsert-chat {:chat-id chat-id (upsert-chat cofx
{:chat-id chat-id
:name chat-name :name chat-name
:is-active true :is-active true
:group-chat true :group-chat true
:group-admin admin :group-admin admin
:contacts participants} cofx)) :contacts participants}))
(defn clear-history (fx/defn clear-history
"Clears history of the particular chat" "Clears history of the particular chat"
[chat-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id]
(let [{:keys [messages (let [{:keys [messages
deleted-at-clock-value]} (get-in db [:chats chat-id]) deleted-at-clock-value]} (get-in db [:chats chat-id])
last-message-clock-value (or (->> messages last-message-clock-value (or (->> messages
@ -100,13 +102,15 @@
:data-store/tx [(chats-store/clear-history-tx chat-id last-message-clock-value) :data-store/tx [(chats-store/clear-history-tx chat-id last-message-clock-value)
(messages-store/delete-messages-tx chat-id)]})) (messages-store/delete-messages-tx chat-id)]}))
(defn- remove-transport [chat-id {:keys [db] :as cofx}] (fx/defn remove-transport
[{:keys [db] :as cofx} chat-id]
;; if this is private group chat, we have to broadcast leave and unsubscribe after that ;; if this is private group chat, we have to broadcast leave and unsubscribe after that
(if (group-chat? chat-id cofx) (if (group-chat? cofx chat-id)
(transport.message/send (transport.group-chat/GroupLeave.) chat-id cofx) (transport.message/send (transport.group-chat/GroupLeave.) chat-id cofx)
(transport.utils/unsubscribe-from-chat chat-id cofx))) (transport.utils/unsubscribe-from-chat cofx chat-id)))
(defn- deactivate-chat [chat-id {:keys [db now] :as cofx}] (fx/defn deactivate-chat
[{:keys [db now] :as cofx} chat-id]
{:db (-> db {:db (-> db
(assoc-in [:chats chat-id :is-active] false) (assoc-in [:chats chat-id :is-active] false)
(assoc-in [:current-chat-id] nil)) (assoc-in [:current-chat-id] nil))
@ -118,26 +122,24 @@
;; (remove chat only after the filter has been removed, probably the safest, ;; (remove chat only after the filter has been removed, probably the safest,
;; flag the chat to ignore new messages, change receive method for public/group chats) ;; flag the chat to ignore new messages, change receive method for public/group chats)
;; For now to keep the code simplier and avoid significant changes, best to leave as it is. ;; For now to keep the code simplier and avoid significant changes, best to leave as it is.
(defn remove-chat (fx/defn remove-chat
"Removes chat completely from app, producing all necessary effects for that" "Removes chat completely from app, producing all necessary effects for that"
[chat-id {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} chat-id]
(letfn [(remove-transport-fx [chat-id cofx] (fx/merge cofx
(when (multi-user-chat? chat-id cofx) #(when (multi-user-chat? % chat-id)
(remove-transport chat-id cofx)))] (remove-transport % chat-id))
(handlers-macro/merge-fx (deactivate-chat chat-id)
cofx (clear-history chat-id)))
(remove-transport-fx chat-id)
(deactivate-chat chat-id)
(clear-history chat-id))))
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}] (fx/defn send-messages-seen
[{:keys [db] :as cofx} chat-id message-ids]
(when (not (get-in db [:chats chat-id :public?])) (when (not (get-in db [:chats chat-id :public?]))
(transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx))) (transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future ;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future
(defn mark-messages-seen (fx/defn mark-messages-seen
"Marks all unviewed loaded messages as seen in particular chat" "Marks all unviewed loaded messages as seen in particular chat"
[chat-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id]
(when-let [all-unviewed-ids (seq (get-in db [:chats chat-id :unviewed-messages]))] (when-let [all-unviewed-ids (seq (get-in db [:chats chat-id :unviewed-messages]))]
(let [me (:current-public-key db) (let [me (:current-public-key db)
updated-statuses (keep (fn [message-id] updated-statuses (keep (fn [message-id]
@ -148,56 +150,53 @@
all-unviewed-ids) all-unviewed-ids)
loaded-unviewed-ids (map :message-id updated-statuses)] loaded-unviewed-ids (map :message-id updated-statuses)]
(when (seq loaded-unviewed-ids) (when (seq loaded-unviewed-ids)
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (-> (reduce (fn [acc {:keys [message-id status]}]
{:db (-> (reduce (fn [acc {:keys [message-id status]}] (assoc-in acc [:chats chat-id :message-statuses
(assoc-in acc [:chats chat-id :message-statuses message-id me :status]
message-id me :status] status))
status)) db
db updated-statuses)
updated-statuses) (update-in [:chats chat-id :unviewed-messages]
(update-in [:chats chat-id :unviewed-messages] #(apply disj % loaded-unviewed-ids)))
#(apply disj % loaded-unviewed-ids))) :data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]} (send-messages-seen chat-id loaded-unviewed-ids))))))
(send-messages-seen chat-id loaded-unviewed-ids))))))
(defn- preload-chat-data (fx/defn preload-chat-data
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat" "Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
[chat-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (-> (assoc db :current-chat-id chat-id) {:db (-> (assoc db :current-chat-id chat-id)
(set-chat-ui-props {:validation-messages nil}))} (set-chat-ui-props {:validation-messages nil}))}
(mark-messages-seen chat-id))) (mark-messages-seen chat-id)))
(defn navigate-to-chat (fx/defn navigate-to-chat
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data" "Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
[chat-id {:keys [modal? navigation-replace?]} cofx] [cofx chat-id {:keys [modal? navigation-replace?]}]
(cond (cond
modal? modal?
(handlers-macro/merge-fx (fx/merge cofx
cofx (navigation/navigate-to-cofx :chat-modal {})
(navigation/navigate-to-cofx :chat-modal {}) (preload-chat-data chat-id))
(preload-chat-data chat-id))
navigation-replace? navigation-replace?
(handlers-macro/merge-fx cofx (fx/merge cofx
(navigation/navigate-reset {:index 1 (navigation/navigate-reset {:index 1
:actions [{:routeName :home} :actions [{:routeName :home}
{:routeName :chat}]}) {:routeName :chat}]})
(preload-chat-data chat-id)) (preload-chat-data chat-id))
:else :else
(handlers-macro/merge-fx cofx (fx/merge cofx
(navigation/navigate-to-cofx :chat {}) (navigation/navigate-to-cofx :chat {})
(preload-chat-data chat-id)))) (preload-chat-data chat-id))))
(defn start-chat (fx/defn start-chat
"Start a chat, making sure it exists" "Start a chat, making sure it exists"
[chat-id opts {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id opts]
;; don't allow to open chat with yourself ;; don't allow to open chat with yourself
(when (not= (:current-public-key db) chat-id) (when (not= (:current-public-key db) chat-id)
(handlers-macro/merge-fx cofx (fx/merge cofx
(upsert-chat {:chat-id chat-id (upsert-chat {:chat-id chat-id
:is-active true}) :is-active true})
(navigate-to-chat chat-id opts)))) (navigate-to-chat chat-id opts))))

View File

@ -7,8 +7,8 @@
[status-im.chat.models :as models.chat] [status-im.chat.models :as models.chat]
[status-im.transport.message.core :as message] [status-im.transport.message.core :as message]
[status-im.transport.message.v1.group-chat :as transport.group-chat] [status-im.transport.message.v1.group-chat :as transport.group-chat]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.chat.models.message :as models.message]
[status-im.chat.models.message :as models.message])) [status-im.utils.fx :as fx]))
(defn- participants-diff [existing-participants-set new-participants-set] (defn- participants-diff [existing-participants-set new-participants-set]
{:removed (set/difference existing-participants-set new-participants-set) {:removed (set/difference existing-participants-set new-participants-set)
@ -41,37 +41,38 @@
admin-name (or (get-in db [:contacts/contacts group-admin :name]) admin-name (or (get-in db [:contacts/contacts group-admin :name])
group-admin)] group-admin)]
(if (removed me) ;; we were removed (if (removed me) ;; we were removed
(handlers-macro/merge-fx cofx (fx/merge cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id random-id now (models.message/system-message chat-id random-id now
(str admin-name " " (i18n/label :t/removed-from-chat)))) (str admin-name " " (i18n/label :t/removed-from-chat))))
(models.chat/upsert-chat {:chat-id chat-id (models.chat/upsert-chat {:chat-id chat-id
:removed-from-at now :removed-from-at now
:is-active false}) :is-active false})
(transport.utils/unsubscribe-from-chat chat-id)) (transport.utils/unsubscribe-from-chat chat-id))
(handlers-macro/merge-fx cofx (fx/merge cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id random-id now (models.message/system-message chat-id random-id now
(prepare-system-message admin-name (prepare-system-message admin-name
added added
removed removed
(:contacts/contacts db)))) (:contacts/contacts db))))
(group/participants-added chat-id added) (group/participants-added chat-id added)
(group/participants-removed chat-id removed))))) (group/participants-removed chat-id removed)))))
;; first time we hear about chat -> create it if we are among participants ;; first time we hear about chat -> create it if we are among participants
(when (get (set participants) me) (when (get (set participants) me)
(models.chat/add-group-chat chat-id chat-name signature participants cofx))))) (models.chat/add-group-chat cofx chat-id chat-name signature participants)))))
(defn handle-group-leave [chat-id signature {:keys [db random-id now] :as cofx}] (fx/defn handle-group-leave
[{:keys [db random-id now] :as cofx} chat-id signature]
(let [me (:current-public-key db) (let [me (:current-public-key db)
participant-leaving-name (or (get-in db [:contacts/contacts signature :name]) participant-leaving-name (or (get-in db [:contacts/contacts signature :name])
signature)] signature)]
(when (and (when (and
(not= signature me) (not= signature me)
(get-in db [:chats chat-id])) ;; chat is present (get-in db [:chats chat-id])) ;; chat is present
(handlers-macro/merge-fx cofx (fx/merge cofx
(models.message/receive (models.message/receive
(models.message/system-message chat-id random-id now (models.message/system-message chat-id random-id now
(str participant-leaving-name " " (i18n/label :t/left)))) (str participant-leaving-name " " (i18n/label :t/left))))
(group/participants-removed chat-id #{signature}) (group/participants-removed chat-id #{signature})
(transport.group-chat/send-new-group-key nil chat-id))))) (transport.group-chat/send-new-group-key nil chat-id)))))

View File

@ -5,7 +5,8 @@
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.datetime :as datetime] [status-im.utils.datetime :as datetime]
[status-im.js-dependencies :as dependencies])) [status-im.js-dependencies :as dependencies]
[status-im.utils.fx :as fx]))
(def space-char " ") (def space-char " ")
@ -89,16 +90,16 @@
(str const/arg-wrapping-char arg const/arg-wrapping-char))))) (str const/arg-wrapping-char arg const/arg-wrapping-char)))))
(str/join const/spacing-char)))) (str/join const/spacing-char))))
(defn set-chat-input-text (fx/defn set-chat-input-text
"Set input text for current-chat. Takes db and input text and cofx "Set input text for current-chat. Takes db and input text and cofx
as arguments and returns new fx. Always clear all validation messages." as arguments and returns new fx. Always clear all validation messages."
[new-input {{:keys [current-chat-id] :as db} :db}] [{{:keys [current-chat-id] :as db} :db} new-input]
{:db (-> (chat-model/set-chat-ui-props db {:validation-messages nil}) {:db (-> (chat-model/set-chat-ui-props db {:validation-messages nil})
(assoc-in [:chats current-chat-id :input-text] (text->emoji new-input)))}) (assoc-in [:chats current-chat-id :input-text] (text->emoji new-input)))})
(defn set-chat-input-metadata (fx/defn set-chat-input-metadata
"Sets user invisible chat input metadata for current-chat" "Sets user invisible chat input metadata for current-chat"
[metadata {:keys [db] :as cofx}] [{:keys [db] :as cofx} metadata]
(let [current-chat-id (:current-chat-id db)] (let [current-chat-id (:current-chat-id db)]
{:db (assoc-in db [:chats current-chat-id :input-metadata] metadata)})) {:db (assoc-in db [:chats current-chat-id :input-metadata] metadata)}))
@ -114,10 +115,11 @@
:chat/spam-messages-frequency 0 :chat/spam-messages-frequency 0
:chat/cooldown-enabled? true)}) :chat/cooldown-enabled? true)})
(defn process-cooldown [{{:keys [chat/last-outgoing-message-sent-at (fx/defn process-cooldown
chat/cooldowns [{{:keys [chat/last-outgoing-message-sent-at
chat/spam-messages-frequency chat/cooldowns
current-chat-id] :as db} :db :as cofx}] chat/spam-messages-frequency
current-chat-id] :as db} :db :as cofx}]
(when (chat-model/public-chat? current-chat-id cofx) (when (chat-model/public-chat? current-chat-id cofx)
(let [spamming-fast? (< (- (datetime/timestamp) last-outgoing-message-sent-at) (let [spamming-fast? (< (- (datetime/timestamp) last-outgoing-message-sent-at)
(+ const/spam-interval-ms (* 1000 cooldowns))) (+ const/spam-interval-ms (* 1000 cooldowns)))

View File

@ -7,11 +7,11 @@
[status-im.chat.commands.core :as commands] [status-im.chat.commands.core :as commands]
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(def index-messages (partial into {} (map (juxt :message-id identity)))) (def index-messages (partial into {} (map (juxt :message-id identity))))
(defn- add-default-contacts (fx/defn add-default-contacts
[{:keys [db default-contacts] :as cofx}] [{:keys [db default-contacts] :as cofx}]
(let [new-contacts (-> {} (let [new-contacts (-> {}
(into (map (fn [[id props]] (into (map (fn [[id props]]
@ -43,10 +43,10 @@
:message-id) :message-id)
message-references)) message-references))
(defn group-chat-messages (fx/defn group-chat-messages
"Takes chat-id, new messages + cofx and properly groups them "Takes chat-id, new messages + cofx and properly groups them
into the `:message-groups`index in db" into the `:message-groups`index in db"
[chat-id messages {:keys [db]}] [{:keys [db]} chat-id messages]
{:db (reduce (fn [db [datemark grouped-messages]] {:db (reduce (fn [db [datemark grouped-messages]]
(update-in db [:chats chat-id :message-groups datemark] (update-in db [:chats chat-id :message-groups datemark]
(fn [message-references] (fn [message-references]
@ -60,14 +60,14 @@
(group-by (comp time/day-relative :timestamp) (group-by (comp time/day-relative :timestamp)
(filter :show? messages)))}) (filter :show? messages)))})
(defn- group-messages (fx/defn group-messages
[{:keys [db]}] [{:keys [db]}]
(reduce-kv (fn [fx chat-id {:keys [messages]}] (reduce-kv (fn [fx chat-id {:keys [messages]}]
(group-chat-messages chat-id (vals messages) fx)) (group-chat-messages fx chat-id (vals messages)))
{:db db} {:db db}
(:chats db))) (:chats db)))
(defn initialize-chats (fx/defn initialize-chats
"Initialize all persisted chats on startup" "Initialize all persisted chats on startup"
[{:keys [db default-dapps all-stored-chats get-stored-messages get-stored-user-statuses [{:keys [db default-dapps all-stored-chats get-stored-messages get-stored-user-statuses
get-stored-unviewed-messages stored-message-ids] :as cofx}] get-stored-unviewed-messages stored-message-ids] :as cofx}]
@ -85,15 +85,15 @@
(set message-ids)))))) (set message-ids))))))
{} {}
all-stored-chats)] all-stored-chats)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db {:db (assoc db
:chats chats :chats chats
:contacts/dapps default-dapps)} :contacts/dapps default-dapps)}
(group-messages) (group-messages)
(add-default-contacts) (add-default-contacts)
(commands/load-commands commands/register)))) (commands/load-commands commands/register))))
(defn initialize-pending-messages (fx/defn initialize-pending-messages
"Change status of own messages which are still in `sending` status to `not-sent` "Change status of own messages which are still in `sending` status to `not-sent`
(If signal from status-go has not been received)" (If signal from status-go has not been received)"
[{:keys [db]}] [{:keys [db]}]
@ -125,14 +125,13 @@
indexed-messages (index-messages new-messages) indexed-messages (index-messages new-messages)
new-message-ids (keys indexed-messages) new-message-ids (keys indexed-messages)
new-statuses (get-stored-user-statuses current-chat-id new-message-ids)] new-statuses (get-stored-user-statuses current-chat-id new-message-ids)]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (-> db
{:db (-> db (update-in [:chats current-chat-id :messages] merge indexed-messages)
(update-in [:chats current-chat-id :messages] merge indexed-messages) (update-in [:chats current-chat-id :message-statuses] merge new-statuses)
(update-in [:chats current-chat-id :message-statuses] merge new-statuses) (update-in [:chats current-chat-id :not-loaded-message-ids]
(update-in [:chats current-chat-id :not-loaded-message-ids] #(apply disj % new-message-ids))
#(apply disj % new-message-ids)) (assoc-in [:chats current-chat-id :all-loaded?]
(assoc-in [:chats current-chat-id :all-loaded?] (> constants/default-number-of-messages (count new-messages))))}
(> constants/default-number-of-messages (count new-messages))))} (group-chat-messages current-chat-id new-messages)
(group-chat-messages current-chat-id new-messages) (chat-model/mark-messages-seen current-chat-id)))))
(chat-model/mark-messages-seen current-chat-id)))))

View File

@ -11,7 +11,6 @@
[status-im.chat.models.input :as input] [status-im.chat.models.input :as input]
[status-im.chat.commands.receiving :as commands-receiving] [status-im.chat.commands.receiving :as commands-receiving]
[status-im.utils.clocks :as utils.clocks] [status-im.utils.clocks :as utils.clocks]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.notifications.core :as notifications] [status-im.notifications.core :as notifications]
[status-im.transport.utils :as transport.utils] [status-im.transport.utils :as transport.utils]
@ -19,7 +18,8 @@
[status-im.transport.message.v1.protocol :as protocol] [status-im.transport.message.v1.protocol :as protocol]
[status-im.data-store.messages :as messages-store] [status-im.data-store.messages :as messages-store]
[status-im.data-store.user-statuses :as user-statuses-store] [status-im.data-store.user-statuses :as user-statuses-store]
[clojure.string :as string])) [clojure.string :as string]
[status-im.utils.fx :as fx]))
(def receive-interceptors (def receive-interceptors
[(re-frame/inject-cofx :random-id)]) [(re-frame/inject-cofx :random-id)])
@ -35,10 +35,10 @@
(not current-chat?) (assoc :appearing? false) (not current-chat?) (assoc :appearing? false)
(emoji-only-content? content) (assoc :content-type constants/content-type-emoji))) (emoji-only-content? content) (assoc :content-type constants/content-type-emoji)))
(defn- re-index-message-groups (fx/defn re-index-message-groups
"Relative datemarks of message groups can get obsolete with passing time, "Relative datemarks of message groups can get obsolete with passing time,
this function re-indexes them for given chat" this function re-indexes them for given chat"
[chat-id {:keys [db]}] [{:keys [db]} chat-id]
(let [chat-messages (get-in db [:chats chat-id :messages])] (let [chat-messages (get-in db [:chats chat-id :messages])]
{:db (update-in db {:db (update-in db
[:chats chat-id :message-groups] [:chats chat-id :message-groups]
@ -56,8 +56,8 @@
(assoc groups new-datemark message-refs)))) (assoc groups new-datemark message-refs))))
{}))})) {}))}))
(defn- add-own-status (fx/defn add-own-status
[chat-id message-id status {:keys [db]}] [{:keys [db]} chat-id message-id status]
(let [me (:current-public-key db) (let [me (:current-public-key db)
status {:chat-id chat-id status {:chat-id chat-id
:message-id message-id :message-id message-id
@ -71,30 +71,28 @@
(defn add-outgoing-status [{:keys [from] :as message} {:keys [db]}] (defn add-outgoing-status [{:keys [from] :as message} {:keys [db]}]
(assoc message :outgoing (= from (:current-public-key db)))) (assoc message :outgoing (= from (:current-public-key db))))
(defn- add-message (fx/defn add-message
[batch? {:keys [chat-id message-id clock-value content] :as message} current-chat? {:keys [db] :as cofx}] [{:keys [db] :as cofx} batch? {:keys [chat-id message-id clock-value content] :as message} current-chat?]
(let [prepared-message (-> message (let [prepared-message (-> message
(prepare-message chat-id current-chat?) (prepare-message chat-id current-chat?)
(add-outgoing-status cofx))] (add-outgoing-status cofx))]
(let [fx {:db (cond-> (let [fx {:db (cond->
(-> db (-> db
(update-in [:chats chat-id :messages] assoc message-id prepared-message) (update-in [:chats chat-id :messages] assoc message-id prepared-message)
;; this will increase last-clock-value twice when sending our own messages ;; this will increase last-clock-value twice when sending our own messages
(update-in [:chats chat-id :last-clock-value] (partial utils.clocks/receive clock-value))) (update-in [:chats chat-id :last-clock-value] (partial utils.clocks/receive clock-value)))
(not current-chat?) (not current-chat?)
(update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id)) (update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id))
:data-store/tx [(messages-store/save-message-tx prepared-message)]}] :data-store/tx [(messages-store/save-message-tx prepared-message)]}]
(if batch? (if batch?
fx fx
(handlers-macro/merge-fx cofx (fx/merge cofx
fx fx
(re-index-message-groups chat-id) (re-index-message-groups chat-id)
(chat-loading/group-chat-messages chat-id [message])))))) (chat-loading/group-chat-messages chat-id [message]))))))
(def ^:private- add-single-message (partial add-message false)) (fx/defn send-message-seen
(def ^:private- add-batch-message (partial add-message true)) [cofx chat-id message-id send-seen?]
(defn- send-message-seen [chat-id message-id send-seen? cofx]
(when send-seen? (when send-seen?
(transport/send (protocol/map->MessagesSeen {:message-ids #{message-id}}) chat-id cofx))) (transport/send (protocol/map->MessagesSeen {:message-ids #{message-id}}) chat-id cofx)))
@ -108,7 +106,8 @@
(= constants/content-type-command-request content-type) (= constants/content-type-command-request content-type)
(assoc :content-type constants/content-type-command))) (assoc :content-type constants/content-type-command)))
(defn- display-notification [chat-id cofx] (fx/defn display-notification
[cofx chat-id]
(when config/in-app-notifications-enabled? (when config/in-app-notifications-enabled?
(let [view-id (get-in cofx [:db :view-id]) (let [view-id (get-in cofx [:db :view-id])
from (get-in cofx [:db :current-public-key]) from (get-in cofx [:db :current-public-key])
@ -120,14 +119,13 @@
:to chat-id :to chat-id
:from from}})))) :from from}}))))
(defn- add-received-message (fx/defn add-received-message
[batch? [{:keys [db now] :as cofx}
{:keys [from message-id chat-id content content-type clock-value js-obj] :as raw-message} batch?
{:keys [db now] :as cofx}] {:keys [from message-id chat-id content content-type clock-value js-obj] :as raw-message}]
(let [{:keys [web3 current-chat-id view-id]} db (let [{:keys [web3 current-chat-id view-id]} db
current-chat? (and (or (= :chat view-id) (= :chat-modal view-id)) (= current-chat-id chat-id)) current-chat? (and (or (= :chat view-id) (= :chat-modal view-id)) (= current-chat-id chat-id))
{:keys [public?] :as chat} (get-in db [:chats chat-id]) {:keys [public?] :as chat} (get-in db [:chats chat-id])
add-message-fn (if batch? add-batch-message add-single-message)
message (-> raw-message message (-> raw-message
(commands-receiving/enhance-receive-parameters cofx) (commands-receiving/enhance-receive-parameters cofx)
(ensure-clock-value chat) (ensure-clock-value chat)
@ -135,57 +133,47 @@
(add-outgoing-status cofx) (add-outgoing-status cofx)
;; TODO (janherich): Remove after couple of releases ;; TODO (janherich): Remove after couple of releases
update-legacy-type)] update-legacy-type)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:confirm-messages-processed [{:web3 web3 {:confirm-messages-processed [{:web3 web3
:js-obj js-obj}]} :js-obj js-obj}]}
(add-message-fn message current-chat?) (add-message batch? message current-chat?)
;; Checking :outgoing here only works for now as we don't have a :seen ;; Checking :outgoing here only works for now as we don't have a :seen
;; status for public chats, if we add processing of our own messages ;; status for public chats, if we add processing of our own messages
;; for 1-to-1 care needs to be taken not to override the :seen status ;; for 1-to-1 care needs to be taken not to override the :seen status
(add-own-status chat-id message-id (cond (:outgoing message) :sent (add-own-status chat-id message-id (cond (:outgoing message) :sent
current-chat? :seen current-chat? :seen
:else :received)) :else :received))
(commands-receiving/receive message) (commands-receiving/receive message)
(display-notification chat-id) (display-notification chat-id)
(send-message-seen chat-id message-id (and (not public?) (send-message-seen chat-id message-id (and (not public?)
current-chat? current-chat?
(not (= constants/system from)) (not (= constants/system from))
(not (:outgoing message))))))) (not (:outgoing message)))))))
(def ^:private add-single-received-message (partial add-received-message false)) (fx/defn receive
(def ^:private add-batch-received-message (partial add-received-message true)) [{:keys [now] :as cofx} {:keys [chat-id message-id] :as message}]
(fx/merge cofx
(chat-model/upsert-chat {:chat-id chat-id
;; We activate a chat again on new messages
:is-active true
:timestamp now})
(add-received-message false message)))
(defn receive (fx/defn update-group-messages [cofx chat->message chat-id]
[{:keys [chat-id message-id] :as message} {:keys [now] :as cofx}] (fx/merge cofx
(handlers-macro/merge-fx cofx (re-index-message-groups chat-id)
(chat-model/upsert-chat {:chat-id chat-id (chat-loading/group-chat-messages chat-id (get chat->message chat-id))))
;; We activate a chat again on new messages
:is-active true
:timestamp now})
(add-single-received-message message)))
(defn receive-many (fx/defn receive-many
[messages {:keys [now] :as cofx}] [{:keys [now] :as cofx} messages]
(let [chat->message (group-by :chat-id messages) (let [chat->message (group-by :chat-id messages)
chat-ids (keys chat->message) chat-ids (keys chat->message)
chat-effects (handlers-macro/merge-effects chats-fx-fns (map #(chat-model/upsert-chat {:chat-id %
cofx :is-active true
(fn [chat-id cofx] :timestamp now}) chat-ids)
(chat-model/upsert-chat {:chat-id chat-id messages-fx-fns (map #(add-received-message true %) messages)
:is-active true groups-fx-fns (map #(update-group-messages chat->message %) chat-ids)]
:timestamp now} (apply fx/merge cofx (concat chats-fx-fns messages-fx-fns groups-fx-fns))))
cofx))
chat-ids)
message-effects (handlers-macro/merge-effects
chat-effects cofx add-batch-received-message messages)]
(handlers-macro/merge-effects
message-effects
cofx
(fn [chat-id cofx]
(handlers-macro/merge-fx cofx
(re-index-message-groups chat-id)
(chat-loading/group-chat-messages chat-id (get chat->message chat-id))))
chat-ids)))
(defn system-message [chat-id message-id timestamp content] (defn system-message [chat-id message-id timestamp content]
{:message-id message-id {:message-id message-id
@ -214,8 +202,8 @@
[(re-frame/inject-cofx :random-id) [(re-frame/inject-cofx :random-id)
(re-frame/inject-cofx :random-id-seq)]) (re-frame/inject-cofx :random-id-seq)])
(defn- send (fx/defn send
[chat-id message-id send-record {{:keys [network-status current-public-key]} :db :as cofx}] [{{:keys [network-status current-public-key]} :db :as cofx} chat-id message-id send-record]
(if (= network-status :offline) (if (= network-status :offline)
{:dispatch-later [{:ms 10000 {:dispatch-later [{:ms 10000
:dispatch [:update-message-status chat-id message-id current-public-key :not-sent]}]} :dispatch [:update-message-status chat-id message-id current-public-key :not-sent]}]}
@ -232,19 +220,19 @@
(def ^:private transport-keys [:content :content-type :message-type :clock-value :timestamp]) (def ^:private transport-keys [:content :content-type :message-type :clock-value :timestamp])
(defn- upsert-and-send [{:keys [chat-id] :as message} {:keys [now] :as cofx}] (fx/defn upsert-and-send [{:keys [now] :as cofx} {:keys [chat-id] :as message}]
(let [send-record (protocol/map->Message (select-keys message transport-keys)) (let [send-record (protocol/map->Message (select-keys message transport-keys))
message-id (transport.utils/message-id send-record) message-id (transport.utils/message-id send-record)
message-with-id (assoc message :message-id message-id)] message-with-id (assoc message :message-id message-id)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(input/process-cooldown) (input/process-cooldown)
(chat-model/upsert-chat {:chat-id chat-id (chat-model/upsert-chat {:chat-id chat-id
:timestamp now}) :timestamp now})
(add-single-message message-with-id true) (add-message false message-with-id true)
(add-own-status chat-id message-id :sending) (add-own-status chat-id message-id :sending)
(send chat-id message-id send-record)))) (send chat-id message-id send-record))))
(defn send-push-notification [fcm-token status cofx] (fx/defn send-push-notification [cofx fcm-token status]
(when (and fcm-token (= status :sent)) (when (and fcm-token (= status :sent))
{:send-notification {:message (js/JSON.stringify #js {:from (get-in cofx [:db :current-public-key]) {:send-notification {:message (js/JSON.stringify #js {:from (get-in cofx [:db :current-public-key])
:to (get-in cofx [:db :current-chat-id])}) :to (get-in cofx [:db :current-chat-id])})
@ -253,7 +241,7 @@
:sound notifications/sound-name} :sound notifications/sound-name}
:tokens [fcm-token]}})) :tokens [fcm-token]}}))
(defn update-message-status [{:keys [chat-id message-id from]} status {:keys [db]}] (fx/defn update-message-status [{:keys [db]} {:keys [chat-id message-id from]} status]
(let [updated-status (-> db (let [updated-status (-> db
(get-in [:chats chat-id :message-statuses message-id from]) (get-in [:chats chat-id :message-statuses message-id from])
(assoc :status status))] (assoc :status status))]
@ -262,17 +250,18 @@
updated-status) updated-status)
:data-store/tx [(user-statuses-store/save-status-tx updated-status)]})) :data-store/tx [(user-statuses-store/save-status-tx updated-status)]}))
(defn resend-message [chat-id message-id cofx] (fx/defn resend-message [cofx chat-id message-id]
(let [message (get-in cofx [:db :chats chat-id :messages message-id]) (let [message (get-in cofx [:db :chats chat-id :messages message-id])
send-record (-> message send-record (-> message
(select-keys transport-keys) (select-keys transport-keys)
(update :message-type keyword) (update :message-type keyword)
protocol/map->Message)] protocol/map->Message)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(send chat-id message-id send-record) (send chat-id message-id send-record)
(update-message-status message :sending)))) (update-message-status message :sending))))
(defn- remove-message-from-group [chat-id {:keys [timestamp message-id]} {:keys [db]}] (fx/defn remove-message-from-group
[{:keys [db]} chat-id {:keys [timestamp message-id]}]
(let [datemark (time/day-relative timestamp)] (let [datemark (time/day-relative timestamp)]
{:db (update-in db [:chats chat-id :message-groups] {:db (update-in db [:chats chat-id :message-groups]
(fn [groups] (fn [groups]
@ -285,16 +274,16 @@
(remove (comp (partial = message-id) :message-id) (remove (comp (partial = message-id) :message-id)
message-references))))))})) message-references))))))}))
(defn delete-message (fx/defn delete-message
"Deletes chat message, along its occurence in all references, like `:message-groups`" "Deletes chat message, along its occurence in all references, like `:message-groups`"
[chat-id message-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id message-id]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (update-in db [:chats chat-id :messages] dissoc message-id)
{:db (update-in db [:chats chat-id :messages] dissoc message-id) :data-store/tx [(messages-store/delete-message-tx message-id)]}
:data-store/tx [(messages-store/delete-message-tx message-id)]} (remove-message-from-group chat-id (get-in db [:chats chat-id :messages message-id]))))
(remove-message-from-group chat-id (get-in db [:chats chat-id :messages message-id]))))
(defn send-message [{:keys [chat-id] :as message} {:keys [db now] :as cofx}] (fx/defn send-message
[{:keys [db now] :as cofx} {:keys [chat-id] :as message}]
(let [{:keys [current-public-key chats]} db (let [{:keys [current-public-key chats]} db
{:keys [last-clock-value] :as chat} (get chats chat-id) {:keys [last-clock-value] :as chat} (get chats chat-id)
message-data (-> message message-data (-> message
@ -304,4 +293,4 @@
last-clock-value) last-clock-value)
:show? true) :show? true)
(add-message-type chat))] (add-message-type chat))]
(upsert-and-send message-data cofx))) (upsert-and-send cofx message-data)))

View File

@ -1,5 +1,4 @@
(ns status-im.events (ns status-im.events
(:require-macros [status-im.utils.handlers-macro :as handlers-macro])
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.accounts.core :as accounts] [status-im.accounts.core :as accounts]
[status-im.accounts.create.core :as accounts.create] [status-im.accounts.create.core :as accounts.create]
@ -27,6 +26,7 @@
:as :as
currency-settings.models] currency-settings.models]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
@ -40,7 +40,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:init.ui/data-reset-cancelled :init.ui/data-reset-cancelled
(fn [cofx [_ encryption-key]] (fn [cofx [_ encryption-key]]
(init/initialize-app encryption-key cofx))) (init/initialize-app cofx encryption-key)))
(handlers/register-handler-fx (handlers/register-handler-fx
:init/app-started :init/app-started
@ -50,12 +50,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/get-encryption-key-success :init.callback/get-encryption-key-success
(fn [cofx [_ encryption-key]] (fn [cofx [_ encryption-key]]
(init/initialize-app encryption-key cofx))) (init/initialize-app cofx encryption-key)))
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/get-device-UUID-success :init.callback/get-device-UUID-success
(fn [cofx [_ device-uuid]] (fn [cofx [_ device-uuid]]
(init/set-device-uuid device-uuid cofx))) (init/set-device-uuid cofx device-uuid)))
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/init-store-success :init.callback/init-store-success
@ -66,7 +66,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/init-store-error :init.callback/init-store-error
(fn [cofx [_ encryption-key error]] (fn [cofx [_ encryption-key error]]
(init/handle-init-store-error encryption-key cofx))) (init/handle-init-store-error cofx encryption-key)))
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/account-change-success :init.callback/account-change-success
@ -85,7 +85,7 @@
(re-frame/inject-cofx :data-store/all-browsers) (re-frame/inject-cofx :data-store/all-browsers)
(re-frame/inject-cofx :data-store/all-dapp-permissions)] (re-frame/inject-cofx :data-store/all-dapp-permissions)]
(fn [cofx [_ address]] (fn [cofx [_ address]]
(init/initialize-account address cofx))) (init/initialize-account cofx address)))
(handlers/register-handler-fx (handlers/register-handler-fx
:init.callback/account-change-error :init.callback/account-change-error
@ -102,39 +102,39 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.ui/mainnet-warning-shown :accounts.ui/mainnet-warning-shown
(fn [cofx _] (fn [cofx _]
(accounts.update/account-update {:mainnet-warning-shown? true} cofx))) (accounts.update/account-update cofx {:mainnet-warning-shown? true} {})))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.ui/dev-mode-switched :accounts.ui/dev-mode-switched
(fn [cofx [_ dev-mode?]] (fn [cofx [_ dev-mode?]]
(accounts/switch-dev-mode dev-mode? cofx))) (accounts/switch-dev-mode cofx dev-mode?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.ui/web3-opt-in-mode-switched :accounts.ui/web3-opt-in-mode-switched
(fn [cofx [_ opt-in]] (fn [cofx [_ opt-in]]
(accounts/switch-web3-opt-in-mode opt-in cofx))) (accounts/switch-web3-opt-in-mode cofx opt-in)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.ui/wallet-set-up-confirmed :accounts.ui/wallet-set-up-confirmed
(fn [cofx [_ modal?]] (fn [cofx [_ modal?]]
(accounts/confirm-wallet-set-up modal? cofx))) (accounts/confirm-wallet-set-up cofx modal?)))
;; accounts create module ;; accounts create module
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.create.ui/next-step-pressed :accounts.create.ui/next-step-pressed
(fn [cofx [_ step password password-confirm]] (fn [cofx [_ step password password-confirm]]
(accounts.create/next-step step password password-confirm cofx))) (accounts.create/next-step cofx step password password-confirm)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.create.ui/step-back-pressed :accounts.create.ui/step-back-pressed
(fn [cofx [_ step password password-confirm]] (fn [cofx [_ step password password-confirm]]
(accounts.create/step-back step cofx))) (accounts.create/step-back cofx step)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.create.ui/input-text-changed :accounts.create.ui/input-text-changed
(fn [cofx [_ input-key text]] (fn [cofx [_ input-key text]]
(accounts.create/account-set-input-text input-key text cofx))) (accounts.create/account-set-input-text cofx input-key text)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.create.callback/create-account-success :accounts.create.callback/create-account-success
@ -142,7 +142,7 @@
(re-frame/inject-cofx :accounts.create/get-signing-phrase) (re-frame/inject-cofx :accounts.create/get-signing-phrase)
(re-frame/inject-cofx :accounts.create/get-status)] (re-frame/inject-cofx :accounts.create/get-status)]
(fn [cofx [_ result password]] (fn [cofx [_ result password]]
(accounts.create/on-account-created result password false cofx))) (accounts.create/on-account-created cofx result password false)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.create.ui/create-new-account-button-pressed :accounts.create.ui/create-new-account-button-pressed
@ -159,7 +159,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/passphrase-input-changed :accounts.recover.ui/passphrase-input-changed
(fn [cofx [_ recovery-phrase]] (fn [cofx [_ recovery-phrase]]
(accounts.recover/set-phrase recovery-phrase cofx))) (accounts.recover/set-phrase cofx recovery-phrase)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/passphrase-input-blured :accounts.recover.ui/passphrase-input-blured
@ -169,7 +169,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/password-input-changed :accounts.recover.ui/password-input-changed
(fn [cofx [_ masked-password]] (fn [cofx [_ masked-password]]
(accounts.recover/set-password masked-password cofx))) (accounts.recover/set-password cofx masked-password)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.recover.ui/password-input-blured :accounts.recover.ui/password-input-blured
@ -192,7 +192,7 @@
(re-frame/inject-cofx :accounts.create/get-signing-phrase) (re-frame/inject-cofx :accounts.create/get-signing-phrase)
(re-frame/inject-cofx :accounts.create/get-status)] (re-frame/inject-cofx :accounts.create/get-status)]
(fn [cofx [_ result password]] (fn [cofx [_ result password]]
(accounts.recover/on-account-recovered result password cofx))) (accounts.recover/on-account-recovered cofx result password)))
;; accounts login module ;; accounts login module
@ -204,24 +204,24 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.login.callback/login-success :accounts.login.callback/login-success
(fn [cofx [_ login-result]] (fn [cofx [_ login-result]]
(accounts.login/user-login-callback login-result cofx))) (accounts.login/user-login-callback cofx login-result)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.login.ui/account-selected :accounts.login.ui/account-selected
(fn [cofx [_ address photo-path name]] (fn [cofx [_ address photo-path name]]
(accounts.login/open-login address photo-path name cofx))) (accounts.login/open-login cofx address photo-path name)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.login.callback/get-user-password-success :accounts.login.callback/get-user-password-success
(fn [cofx [_ password]] (fn [cofx [_ password]]
(accounts.login/open-login-callback password cofx))) (accounts.login/open-login-callback cofx password)))
;; accounts logout module ;; accounts logout module
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.logout.ui/logout-pressed :accounts.logout.ui/logout-pressed
(fn [cofx _] (fn [cofx _]
(accounts.logout/show-logout-confirmation))) (accounts.logout/show-logout-confirmation cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.logout.ui/logout-confirmed :accounts.logout.ui/logout-confirmed
@ -240,17 +240,17 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/user-defined-mailserver-selected :mailserver.ui/user-defined-mailserver-selected
(fn [cofx [_ mailserver-id]] (fn [cofx [_ mailserver-id]]
(mailserver/edit mailserver-id cofx))) (mailserver/edit cofx mailserver-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/default-mailserver-selected :mailserver.ui/default-mailserver-selected
(fn [cofx [_ mailserver-id]] (fn [cofx [_ mailserver-id]]
(mailserver/show-connection-confirmation mailserver-id cofx))) (mailserver/show-connection-confirmation cofx mailserver-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/add-pressed :mailserver.ui/add-pressed
(fn [cofx _] (fn [cofx _]
(navigation/navigate-to-cofx :edit-mailserver nil cofx))) (navigation/navigate-to-cofx cofx :edit-mailserver nil)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/save-pressed :mailserver.ui/save-pressed
@ -261,7 +261,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/input-changed :mailserver.ui/input-changed
(fn [cofx [_ input-key value]] (fn [cofx [_ input-key value]]
(mailserver/set-input input-key value cofx))) (mailserver/set-input cofx input-key value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/delete-confirmed :mailserver.ui/delete-confirmed
@ -271,22 +271,22 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/delete-pressed :mailserver.ui/delete-pressed
(fn [cofx [_ mailserver-id]] (fn [cofx [_ mailserver-id]]
(mailserver/show-delete-confirmation mailserver-id cofx))) (mailserver/show-delete-confirmation cofx mailserver-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.callback/qr-code-scanned :mailserver.callback/qr-code-scanned
(fn [cofx [_ _ url]] (fn [cofx [_ _ url]]
(mailserver/set-url-from-qr url cofx))) (mailserver/set-url-from-qr cofx url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/connect-pressed :mailserver.ui/connect-pressed
(fn [cofx [_ mailserver-id]] (fn [cofx [_ mailserver-id]]
(mailserver/show-connection-confirmation mailserver-id cofx))) (mailserver/show-connection-confirmation cofx mailserver-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/connect-confirmed :mailserver.ui/connect-confirmed
(fn [cofx [_ current-fleet mailserver-id]] (fn [cofx [_ current-fleet mailserver-id]]
(mailserver/save-settings current-fleet mailserver-id cofx))) (mailserver/save-settings cofx current-fleet mailserver-id)))
;; network module ;; network module
@ -299,7 +299,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:network.ui/input-changed :network.ui/input-changed
(fn [cofx [_ input-key value]] (fn [cofx [_ input-key value]]
(network/set-input input-key value cofx))) (network/set-input cofx input-key value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:network.ui/add-network-pressed :network.ui/add-network-pressed
@ -314,12 +314,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:network.ui/save-non-rpc-network-pressed :network.ui/save-non-rpc-network-pressed
(fn [cofx [_ network]] (fn [cofx [_ network]]
(network/save-non-rpc-network network cofx))) (network/save-non-rpc-network cofx network)))
(handlers/register-handler-fx (handlers/register-handler-fx
:network.ui/remove-network-confirmed :network.ui/remove-network-confirmed
(fn [cofx [_ network]] (fn [cofx [_ network]]
(network/remove-network network cofx))) (network/remove-network cofx network)))
(handlers/register-handler-fx (handlers/register-handler-fx
:network.ui/connect-network-pressed :network.ui/connect-network-pressed
@ -334,46 +334,46 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:network/connection-status-changed :network/connection-status-changed
(fn [{db :db :as cofx} [_ is-connected?]] (fn [{db :db :as cofx} [_ is-connected?]]
(network/handle-connection-status-change is-connected? cofx))) (network/handle-connection-status-change cofx is-connected?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:network/network-status-changed :network/network-status-changed
(fn [cofx [_ data]] (fn [cofx [_ data]]
(network/handle-network-status-change data cofx))) (network/handle-network-status-change cofx data)))
;; fleet module ;; fleet module
(handlers/register-handler-fx (handlers/register-handler-fx
:fleet.ui/save-fleet-confirmed :fleet.ui/save-fleet-confirmed
(fn [cofx [_ fleet]] (fn [cofx [_ fleet]]
(fleet/save fleet cofx))) (fleet/save cofx fleet)))
(handlers/register-handler-fx (handlers/register-handler-fx
:fleet.ui/fleet-selected :fleet.ui/fleet-selected
(fn [cofx [_ fleet]] (fn [cofx [_ fleet]]
(fleet/show-save-confirmation fleet cofx))) (fleet/show-save-confirmation cofx fleet)))
;; bootnodes module ;; bootnodes module
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/custom-bootnodes-switch-toggled :bootnodes.ui/custom-bootnodes-switch-toggled
(fn [cofx [_ value]] (fn [cofx [_ value]]
(bootnodes/toggle-custom-bootnodes value cofx))) (bootnodes/toggle-custom-bootnodes cofx value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/add-bootnode-pressed :bootnodes.ui/add-bootnode-pressed
(fn [cofx [_ bootnode-id]] (fn [cofx [_ bootnode-id]]
(bootnodes/edit bootnode-id cofx))) (bootnodes/edit cofx bootnode-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.callback/qr-code-scanned :bootnodes.callback/qr-code-scanned
(fn [cofx [_ _ url]] (fn [cofx [_ _ url]]
(bootnodes/set-bootnodes-from-qr url cofx))) (bootnodes/set-bootnodes-from-qr cofx url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/input-changed :bootnodes.ui/input-changed
(fn [cofx [_ input-key value]] (fn [cofx [_ input-key value]]
(bootnodes/set-input input-key value cofx))) (bootnodes/set-input cofx input-key value)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/save-pressed :bootnodes.ui/save-pressed
@ -384,57 +384,57 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/delete-pressed :bootnodes.ui/delete-pressed
(fn [_ [_ id]] (fn [_ [_ id]]
(bootnodes/show-delete-bootnode-confirmation id))) (bootnodes/show-delete-bootnode-confirmation _ id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnodes.ui/delete-confirmed :bootnodes.ui/delete-confirmed
(fn [cofx [_ bootnode-id]] (fn [cofx [_ bootnode-id]]
(bootnodes/delete-bootnode bootnode-id cofx))) (bootnodes/delete-bootnode cofx bootnode-id)))
;; log-level module ;; log-level module
(handlers/register-handler-fx (handlers/register-handler-fx
:log-level.ui/change-log-level-confirmed :log-level.ui/change-log-level-confirmed
(fn [cofx [_ log-level]] (fn [cofx [_ log-level]]
(log-level/save-log-level log-level cofx))) (log-level/save-log-level cofx log-level)))
(handlers/register-handler-fx (handlers/register-handler-fx
:log-level.ui/log-level-selected :log-level.ui/log-level-selected
(fn [cofx [_ log-level]] (fn [cofx [_ log-level]]
(log-level/show-change-log-level-confirmation log-level cofx))) (log-level/show-change-log-level-confirmation cofx log-level)))
;; Browser bridge module ;; Browser bridge module
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.bridge.callback/qr-code-scanned :browser.bridge.callback/qr-code-scanned
(fn [cofx [_ _ data message]] (fn [cofx [_ _ data message]]
(browser/handle-scanned-qr-code data message cofx))) (browser/handle-scanned-qr-code cofx data message)))
;; qr-scanner module ;; qr-scanner module
(handlers/register-handler-fx (handlers/register-handler-fx
:qr-scanner.ui/scan-qr-code-pressed :qr-scanner.ui/scan-qr-code-pressed
(fn [cofx [_ identifier handler & [opts]]] (fn [cofx [_ identifier handler & [opts]]]
(qr-scanner/scan-qr-code identifier (merge {:handler handler} opts) cofx))) (qr-scanner/scan-qr-code cofx identifier (merge {:handler handler} opts))))
(handlers/register-handler-fx (handlers/register-handler-fx
:qr-scanner.callback/scan-qr-code-success :qr-scanner.callback/scan-qr-code-success
(fn [cofx [_ context data]] (fn [cofx [_ context data]]
(qr-scanner/set-qr-code context data cofx))) (qr-scanner/set-qr-code cofx context data)))
;; privacy-policy module ;; privacy-policy module
(handlers/register-handler-fx (handlers/register-handler-fx
:privacy-policy/privacy-policy-button-pressed :privacy-policy/privacy-policy-button-pressed
(fn [_ _] (fn [cofx _]
(privacy-policy/open-privacy-policy-link))) (privacy-policy/open-privacy-policy-link cofx)))
;; wallet modules ;; wallet modules
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet.settings.ui/currency-selected :wallet.settings.ui/currency-selected
(fn [cofx [_ currency]] (fn [cofx [_ currency]]
(currency-settings.models/set-currency currency cofx))) (currency-settings.models/set-currency cofx currency)))
;; chat module ;; chat module
@ -460,14 +460,14 @@
:signals/signal-received :signals/signal-received
(fn [cofx [_ event-str]] (fn [cofx [_ event-str]]
(log/debug :event-str event-str) (log/debug :event-str event-str)
(signals/process event-str cofx))) (signals/process cofx event-str)))
;; protocol module ;; protocol module
(handlers/register-handler-fx (handlers/register-handler-fx
:protocol.ui/close-app-confirmed :protocol.ui/close-app-confirmed
(fn [_ _] (fn [cofx _]
(protocol/handle-close-app-confirmed))) (protocol/handle-close-app-confirmed cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:protocol/state-sync-timed-out :protocol/state-sync-timed-out
@ -486,7 +486,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:notifications/notification-event-received :notifications/notification-event-received
(fn [cofx [_ event]] (fn [cofx [_ event]]
(notifications/handle-push-notification event cofx))) (notifications/handle-push-notification cofx event)))
(handlers/register-handler-fx (handlers/register-handler-fx
:notifications.callback/notification-stored :notifications.callback/notification-stored
@ -513,12 +513,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/check-nfc-support-success :hardwallet.callback/check-nfc-support-success
(fn [cofx [_ supported?]] (fn [cofx [_ supported?]]
(hardwallet/set-nfc-support supported? cofx))) (hardwallet/set-nfc-support cofx supported?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.callback/check-nfc-enabled-success :hardwallet.callback/check-nfc-enabled-success
(fn [cofx [_ enabled?]] (fn [cofx [_ enabled?]]
(hardwallet/set-nfc-enabled enabled? cofx))) (hardwallet/set-nfc-enabled cofx enabled?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/status-hardwallet-option-pressed :hardwallet.ui/status-hardwallet-option-pressed
@ -538,14 +538,14 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/connect-info-button-pressed :hardwallet.ui/connect-info-button-pressed
(fn [cofx _] (fn [cofx _]
(browser/open-url "https://hardwallet.status.im" cofx))) (browser/open-url cofx "https://hardwallet.status.im")))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/hold-card-button-pressed :hardwallet.ui/hold-card-button-pressed
(fn [{:keys [db] :as cofx} _] (fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)} {:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil)))) (navigation/navigate-to-cofx :hardwallet-setup nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/begin-setup-button-pressed :hardwallet.ui/begin-setup-button-pressed
@ -562,9 +562,9 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/connection-error-confirm-button-pressed :hardwallet.ui/connection-error-confirm-button-pressed
(fn [{:keys [db] :as cofx} _] (fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)} {:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil)))) (navigation/navigate-to-cofx :hardwallet-setup nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/secret-keys-next-button-pressed :hardwallet.ui/secret-keys-next-button-pressed
@ -584,12 +584,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/success-button-pressed :hardwallet.ui/success-button-pressed
(fn [cofx _] (fn [cofx _]
(navigation/navigate-to-cofx :home nil cofx))) (navigation/navigate-to-cofx cofx :home nil)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/pin-numpad-button-pressed :hardwallet.ui/pin-numpad-button-pressed
(fn [cofx [_ number step]] (fn [cofx [_ number step]]
(hardwallet/process-pin-input number step cofx))) (hardwallet/process-pin-input cofx number step)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hardwallet.ui/pin-numpad-delete-button-pressed :hardwallet.ui/pin-numpad-delete-button-pressed
@ -602,42 +602,42 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/browser-item-selected :browser.ui/browser-item-selected
(fn [cofx [_ browser-id]] (fn [cofx [_ browser-id]]
(browser/open-existing-browser browser-id cofx))) (browser/open-existing-browser cofx browser-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/url-input-pressed :browser.ui/url-input-pressed
(fn [cofx _] (fn [cofx _]
(browser/update-browser-option :url-editing? true cofx))) (browser/update-browser-option cofx :url-editing? true)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/url-input-blured :browser.ui/url-input-blured
(fn [cofx _] (fn [cofx _]
(browser/update-browser-option :url-editing? false cofx))) (browser/update-browser-option cofx :url-editing? false)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/url-submitted :browser.ui/url-submitted
(fn [cofx [_ url]] (fn [cofx [_ url]]
(browser/open-url-in-current-browser url cofx))) (browser/open-url-in-current-browser cofx url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/message-link-pressed :browser.ui/message-link-pressed
(fn [cofx [_ link]] (fn [cofx [_ link]]
(browser/handle-message-link link cofx))) (browser/handle-message-link cofx link)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/remove-browser-pressed :browser.ui/remove-browser-pressed
(fn [cofx [_ browser-id]] (fn [cofx [_ browser-id]]
(browser/remove-browser browser-id cofx))) (browser/remove-browser cofx browser-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/lock-pressed :browser.ui/lock-pressed
(fn [cofx [_ secure?]] (fn [cofx [_ secure?]]
(browser/update-browser-option :show-tooltip (if secure? :secure :not-secure) cofx))) (browser/update-browser-option cofx :show-tooltip (if secure? :secure :not-secure))))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/close-tooltip-pressed :browser.ui/close-tooltip-pressed
(fn [cofx _] (fn [cofx _]
(browser/update-browser-option :show-tooltip nil cofx))) (browser/update-browser-option cofx :show-tooltip nil)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/previous-page-button-pressed :browser.ui/previous-page-button-pressed
@ -652,12 +652,12 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:browser/navigation-state-changed :browser/navigation-state-changed
(fn [cofx [_ event error?]] (fn [cofx [_ event error?]]
(browser/navigation-state-changed event error? cofx))) (browser/navigation-state-changed cofx event error?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser/bridge-message-received :browser/bridge-message-received
(fn [cofx [_ message]] (fn [cofx [_ message]]
(browser/process-bridge-message message cofx))) (browser/process-bridge-message cofx message)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser/error-occured :browser/error-occured
@ -667,49 +667,49 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:browser/loading-started :browser/loading-started
(fn [cofx _] (fn [cofx _]
(browser/update-browser-option :error? false cofx))) (browser/update-browser-option cofx :error? false)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.callback/resolve-ens-multihash-success :browser.callback/resolve-ens-multihash-success
(fn [cofx [_ hash]] (fn [cofx [_ hash]]
(browser/resolve-ens-multihash-success hash cofx))) (browser/resolve-ens-multihash-success cofx hash)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.callback/resolve-ens-multihash-error :browser.callback/resolve-ens-multihash-error
(fn [cofx _] (fn [cofx _]
(browser/update-browser-option :resolving? false cofx))) (browser/update-browser-option cofx :resolving? false)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.callback/call-rpc :browser.callback/call-rpc
(fn [cofx [_ message]] (fn [cofx [_ message]]
(browser/send-to-bridge message cofx))) (browser/send-to-bridge cofx message)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.permissions.ui/dapp-permission-allowed :browser.permissions.ui/dapp-permission-allowed
(fn [cofx [_ dapp-name permission]] (fn [cofx [_ dapp-name permission]]
(browser.permissions/allow-permission dapp-name permission cofx))) (browser.permissions/allow-permission cofx dapp-name permission)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.permissions.ui/dapp-permission-denied :browser.permissions.ui/dapp-permission-denied
(fn [cofx [_ dapp-name]] (fn [cofx [_ dapp-name]]
(browser.permissions/process-next-permission dapp-name cofx))) (browser.permissions/process-next-permission cofx dapp-name)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/open-in-status-option-selected :browser.ui/open-in-status-option-selected
(fn [cofx [_ url]] (fn [cofx [_ url]]
(browser/open-url url cofx))) (browser/open-url cofx url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/open-dapp-button-pressed :browser.ui/open-dapp-button-pressed
(fn [cofx [_ dapp-url]] (fn [cofx [_ dapp-url]]
(browser/open-url dapp-url cofx))) (browser/open-url cofx dapp-url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/dapp-url-submitted :browser.ui/dapp-url-submitted
(fn [cofx [_ dapp-url]] (fn [cofx [_ dapp-url]]
(browser/open-url dapp-url cofx))) (browser/open-url cofx dapp-url)))
(handlers/register-handler-fx (handlers/register-handler-fx
:browser.ui/open-modal-chat-button-pressed :browser.ui/open-modal-chat-button-pressed
(fn [cofx [_ host]] (fn [cofx [_ host]]
(browser/open-chat-from-browser host cofx))) (browser/open-chat-from-browser cofx host)))

View File

@ -4,8 +4,8 @@
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.types :as types]
[status-im.utils.types :as types]) [status-im.utils.fx :as fx])
(:require-macros [status-im.utils.slurp :refer [slurp]])) (:require-macros [status-im.utils.slurp :refer [slurp]]))
(defn current-fleet (defn current-fleet
@ -40,8 +40,8 @@
{} {}
fleets)) fleets))
(defn show-save-confirmation (fx/defn show-save-confirmation
[fleet {:keys [db] :as cofx}] [{:keys [db] :as cofx} fleet]
{:ui/show-confirmation {:title (i18n/label :t/close-app-title) {:ui/show-confirmation {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/change-fleet :content (i18n/label :t/change-fleet
{:fleet fleet}) {:fleet fleet})
@ -49,12 +49,11 @@
:on-accept #(re-frame/dispatch [:fleet.ui/save-fleet-confirmed (keyword fleet)]) :on-accept #(re-frame/dispatch [:fleet.ui/save-fleet-confirmed (keyword fleet)])
:on-cancel nil}}) :on-cancel nil}})
(defn save (fx/defn save
[fleet {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} fleet]
(let [settings (get-in db [:account/account :settings])] (let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx (accounts.update/update-settings cofx
(accounts.update/update-settings (if fleet
(if fleet (assoc settings :fleet fleet)
(assoc settings :fleet fleet) (dissoc settings :fleet))
(dissoc settings :fleet)) {:success-event [:accounts.update.callback/save-settings-success]})))
[:accounts.update.callback/save-settings-success]))))

View File

@ -1,10 +1,10 @@
(ns status-im.hardwallet.core (ns status-im.hardwallet.core
(:require-macros [status-im.utils.handlers-macro :as handlers-macro]) (:require [re-frame.core :as re-frame]
(:require [status-im.utils.platform :as platform]
[status-im.utils.config :as config]
[status-im.react-native.js-dependencies :as js-dependencies] [status-im.react-native.js-dependencies :as js-dependencies]
[re-frame.core :as re-frame] [status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.navigation :as navigation])) [status-im.utils.config :as config]
[status-im.utils.fx :as fx]
[status-im.utils.platform :as platform]))
(defn check-nfc-support [] (defn check-nfc-support []
(when config/hardwallet-enabled? (when config/hardwallet-enabled?
@ -20,10 +20,12 @@
isEnabled isEnabled
(then #(re-frame/dispatch [:hardwallet.callback/check-nfc-enabled-success %]))))) (then #(re-frame/dispatch [:hardwallet.callback/check-nfc-enabled-success %])))))
(defn set-nfc-support [supported? {:keys [db]}] (fx/defn set-nfc-support
[{:keys [db]} supported?]
{:db (assoc-in db [:hardwallet :nfc-supported?] supported?)}) {:db (assoc-in db [:hardwallet :nfc-supported?] supported?)})
(defn set-nfc-enabled [enabled? {:keys [db]}] (fx/defn set-nfc-enabled
[{:keys [db]} enabled?]
{:db (assoc-in db [:hardwallet :nfc-enabled?] enabled?)}) {:db (assoc-in db [:hardwallet :nfc-enabled?] enabled?)})
(defn open-nfc-settings [] (defn open-nfc-settings []
@ -32,20 +34,18 @@
-default -default
goToNfcSetting))) goToNfcSetting)))
(defn navigate-to-connect-screen [cofx] (fx/defn navigate-to-connect-screen [cofx]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:hardwallet/check-nfc-enabled nil}
{:hardwallet/check-nfc-enabled nil} (navigation/navigate-to-cofx :hardwallet-connect nil)))
(navigation/navigate-to-cofx :hardwallet-connect nil)))
(defn hardwallet-supported? [db] (defn hardwallet-supported? [db]
(and config/hardwallet-enabled? (and config/hardwallet-enabled?
platform/android? platform/android?
(get-in db [:hardwallet :nfc-supported?]))) (get-in db [:hardwallet :nfc-supported?])))
(defn return-back-from-nfc-settings [app-coming-from-background? {:keys [db]}] (fx/defn return-back-from-nfc-settings [{:keys [db]}]
(when (and app-coming-from-background? (when (= :hardwallet-connect (:view-id db))
(= :hardwallet-connect (:view-id db)))
{:hardwallet/check-nfc-enabled nil})) {:hardwallet/check-nfc-enabled nil}))
(defn- proceed-to-pin-confirmation [fx] (defn- proceed-to-pin-confirmation [fx]
@ -61,7 +61,8 @@
:confirmation [] :confirmation []
:enter-step :original})) :enter-step :original}))
(defn process-pin-input [number enter-step {:keys [db]}] (fx/defn process-pin-input
[{:keys [db]} number enter-step]
(let [db' (update-in db [:hardwallet :pin enter-step] conj number) (let [db' (update-in db [:hardwallet :pin enter-step] conj number)
numbers-entered (count (get-in db' [:hardwallet :pin enter-step]))] numbers-entered (count (get-in db' [:hardwallet :pin enter-step]))]
(cond-> {:db (assoc-in db' [:hardwallet :pin :status] nil)} (cond-> {:db (assoc-in db' [:hardwallet :pin :status] nil)}

View File

@ -21,12 +21,12 @@
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.keychain.core :as keychain] [status-im.utils.keychain.core :as keychain]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.universal-links.core :as universal-links] [status-im.utils.universal-links.core :as universal-links]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn init-store! (defn init-store!
"Try to decrypt the database, move on if successful otherwise go back to "Try to decrypt the database, move on if successful otherwise go back to
@ -55,12 +55,12 @@
(then reset-keychain!) (then reset-keychain!)
(catch reset-keychain!))) (catch reset-keychain!)))
(defn initialize-keychain (fx/defn initialize-keychain
"Entrypoint, fetches the key from the keychain and initialize the app" "Entrypoint, fetches the key from the keychain and initialize the app"
[cofx] [cofx]
{:keychain/get-encryption-key [:init.callback/get-encryption-key-success]}) {:keychain/get-encryption-key [:init.callback/get-encryption-key-success]})
(defn initialize-app-db (fx/defn initialize-app-db
"Initialize db to initial state" "Initialize db to initial state"
[{{:keys [status-module-initialized? status-node-started? view-id [{{:keys [status-module-initialized? status-node-started? view-id
network-status network peers-count peers-summary device-UUID] network-status network peers-count peers-summary device-UUID]
@ -76,25 +76,26 @@
:device-UUID device-UUID :device-UUID device-UUID
:view-id view-id)}) :view-id view-id)})
(defn initialize-app (fx/defn initialize-app
[encryption-key cofx] [cofx encryption-key]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:init/get-device-UUID nil {:init/get-device-UUID nil
:init/init-store encryption-key :init/init-store encryption-key
:ui/listen-to-window-dimensions-change nil :ui/listen-to-window-dimensions-change nil
:init/testfairy-alert nil :init/testfairy-alert nil
:notifications/handle-initial-push-notification nil :notifications/handle-initial-push-notification nil
:network/listen-to-network-status nil :network/listen-to-network-status nil
:network/listen-to-connection-status nil :network/listen-to-connection-status nil
:hardwallet/check-nfc-support nil :hardwallet/check-nfc-support nil
:hardwallet/check-nfc-enabled nil} :hardwallet/check-nfc-enabled nil}
(initialize-app-db) (initialize-app-db)
(node/start))) (node/start nil)))
(defn set-device-uuid [device-uuid {:keys [db]}] (fx/defn set-device-uuid
[{:keys [db]} device-uuid]
{:db (assoc db :device-UUID device-uuid)}) {:db (assoc db :device-UUID device-uuid)})
(defn handle-change-account-error (fx/defn handle-change-account-error
[cofx] [cofx]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :invalid-key-title) {:title (i18n/label :invalid-key-title)
@ -105,7 +106,7 @@
:on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""]) :on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""])
:on-accept #(re-frame/dispatch [:init.ui/data-reset-accepted])}}) :on-accept #(re-frame/dispatch [:init.ui/data-reset-accepted])}})
(defn handle-init-store-error (fx/defn handle-init-store-error
[encryption-key cofx] [encryption-key cofx]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :decryption-failed-title) {:title (i18n/label :decryption-failed-title)
@ -116,28 +117,29 @@
:on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled encryption-key]) :on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled encryption-key])
:on-accept #(re-frame/dispatch [:init.ui/data-reset-accepted])}}) :on-accept #(re-frame/dispatch [:init.ui/data-reset-accepted])}})
(defn load-accounts [{:keys [db all-accounts]}] (fx/defn load-accounts [{:keys [db all-accounts]}]
(let [accounts (->> all-accounts (let [accounts (->> all-accounts
(map (fn [{:keys [address] :as account}] (map (fn [{:keys [address] :as account}]
[address account])) [address account]))
(into {}))] (into {}))]
{:db (assoc db :accounts/accounts accounts)})) {:db (assoc db :accounts/accounts accounts)}))
(defn initialize-views [cofx] (fx/defn initialize-views
[cofx]
(let [{{:accounts/keys [accounts] :as db} :db} cofx] (let [{{:accounts/keys [accounts] :as db} :db} cofx]
(if (empty? accounts) (if (empty? accounts)
(navigation/navigate-to-clean :intro cofx) (navigation/navigate-to-clean cofx :intro nil)
(let [{:keys [address photo-path name]} (first (sort-by :last-sign-in > (vals accounts)))] (let [{:keys [address photo-path name]} (first (sort-by :last-sign-in > (vals accounts)))]
(accounts.login/open-login address photo-path name cofx))))) (accounts.login/open-login cofx address photo-path name)))))
(defn load-accounts-and-initialize-views (fx/defn load-accounts-and-initialize-views
"DB has been decrypted, load accounts and initialize-view" "DB has been decrypted, load accounts and initialize-view"
[cofx] [cofx]
(handlers-macro/merge-fx cofx (fx/merge cofx
(load-accounts) (load-accounts)
(initialize-views))) (initialize-views)))
(defn initialize-account-db [address {:keys [db web3]}] (fx/defn initialize-account-db [{:keys [db web3]} address]
(let [{:universal-links/keys [url] (let [{:universal-links/keys [url]
:keys [accounts/accounts accounts/create contacts/contacts networks/networks :keys [accounts/accounts accounts/create contacts/contacts networks/networks
network network-status peers-count peers-summary view-id navigation-stack network network-status peers-count peers-summary view-id navigation-stack
@ -168,38 +170,46 @@
(assoc-in [:accounts/create :step] :enter-name))})) (assoc-in [:accounts/create :step] :enter-name))}))
(defn initialize-wallet [cofx] (defn initialize-wallet [cofx]
(when-not platform/desktop? (fx/merge cofx
(handlers-macro/merge-fx cofx (models.wallet/update-wallet)
(models.wallet/update-wallet) (transactions/run-update)
(transactions/run-update) (transactions/start-sync)))
(transactions/start-sync))))
(defn login-only-events [address {:keys [db] :as cofx}] (defn login-only-events [cofx address]
(when (not= (:view-id db) :create-account) (fx/merge cofx
(handlers-macro/merge-fx cofx {:notifications/request-notifications-permissions nil}
{:notifications/request-notifications-permissions nil} (navigation/navigate-to-cofx :home nil)
(navigation/navigate-to-cofx :home nil) (universal-links/process-stored-event)
(universal-links/process-stored-event) (notifications/process-stored-event address)))
(notifications/process-stored-event address))))
(defn initialize-account [address {:keys [web3] :as cofx}] (defn dev-mode? [cofx]
(handlers-macro/merge-fx cofx (get-in [:db :account/account :dev-mode?] cofx))
{:web3/set-default-account [web3 address]
:web3/fetch-node-version [web3 (defn creating-account? [cofx]
#(re-frame/dispatch (= (get-in cofx [:db :view-id])
[:web3/fetch-node-version-callback %])] :create-account))
:notifications/get-fcm-token nil}
(initialize-account-db address) (fx/defn initialize-account [{:keys [db web3] :as cofx} address]
(protocol/initialize-protocol address) (fx/merge cofx
(models.contacts/load-contacts) {:web3/set-default-account [web3 address]
(models.dev-server/start-if-needed) :web3/fetch-node-version [web3
(chat-loading/initialize-chats) #(re-frame/dispatch
(chat-loading/initialize-pending-messages) [:web3/fetch-node-version-callback %])]
(browser/initialize-browsers) :notifications/get-fcm-token nil}
(browser/initialize-dapp-permissions) (initialize-account-db address)
(initialize-wallet) (protocol/initialize-protocol address)
(accounts.update/update-sign-in-time) (models.contacts/load-contacts)
(login-only-events address))) #(when (dev-mode? %)
(models.dev-server/start))
(chat-loading/initialize-chats)
(chat-loading/initialize-pending-messages)
(browser/initialize-browsers)
(browser/initialize-dapp-permissions)
#(when-not platform/desktop?
(initialize-wallet %))
(accounts.update/update-sign-in-time)
#(when-not (creating-account? %)
(login-only-events % address))))
(re-frame/reg-fx (re-frame/reg-fx
:init/init-store :init/init-store

View File

@ -2,20 +2,19 @@
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.accounts.update.core :as accounts.update] [status-im.accounts.update.core :as accounts.update]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn save-log-level (fx/defn save-log-level
[log-level {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} log-level]
(let [settings (get-in db [:account/account :settings])] (let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx (accounts.update/update-settings cofx
(accounts.update/update-settings (if log-level
(if log-level (assoc settings :log-level log-level)
(assoc settings :log-level log-level) (dissoc settings :log-level))
(dissoc settings :log-level)) {:success-event [:accounts.update.callback/save-settings-success]})))
[:accounts.update.callback/save-settings-success]))))
(defn show-change-log-level-confirmation (fx/defn show-change-log-level-confirmation
[{:keys [name value] :as log-level} {:keys [db]}] [{:keys [db]} {:keys [name value] :as log-level}]
{:ui/show-confirmation {:title (i18n/label :t/close-app-title) {:ui/show-confirmation {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/change-log-level :content (i18n/label :t/change-log-level
{:log-level name}) {:log-level name})

View File

@ -5,7 +5,8 @@
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.fleet.core :as fleet] [status-im.fleet.core :as fleet]
[status-im.accounts.update.core :as accounts.update] [status-im.accounts.update.core :as accounts.update]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]
[status-im.ui.screens.navigation :as navigation]))
(def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
(def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
@ -26,7 +27,7 @@
(let [[initial host] (extract-address-components address)] (let [[initial host] (extract-address-components address)]
(str "enode://" initial ":" password "@" host))) (str "enode://" initial ":" password "@" host)))
(defn set-input [input-key value {:keys [db]}] (fx/defn set-input [{:keys [db]} input-key value]
{:db (update {:db (update
db db
:mailservers/manage :mailservers/manage
@ -51,14 +52,14 @@
:id id :id id
:name mailserver-name)) :name mailserver-name))
(defn connected? [id {:keys [db]}] (defn connected? [{:keys [db]} id]
(= (:inbox/current-id db) id)) (= (:inbox/current-id db) id))
(defn fetch [id {:keys [db] :as cofx}] (defn fetch [{:keys [db] :as cofx} id]
(get-in db [:inbox/wnodes (fleet/current-fleet db) id])) (get-in db [:inbox/wnodes (fleet/current-fleet db) id]))
(defn fetch-current [{:keys [db] :as cofx}] (defn fetch-current [{:keys [db] :as cofx}]
(fetch (:inbox/current-id db) cofx)) (fetch cofx (:inbox/current-id db)))
(defn preferred-mailserver-id [{:keys [db] :as cofx}] (defn preferred-mailserver-id [{:keys [db] :as cofx}]
(get-in db [:account/account :settings :wnode (fleet/current-fleet db)])) (get-in db [:account/account :settings :wnode (fleet/current-fleet db)]))
@ -87,7 +88,7 @@
preference (preferred-mailserver-id cofx) preference (preferred-mailserver-id cofx)
choices (-> db :inbox/wnodes current-fleet keys)] choices (-> db :inbox/wnodes current-fleet keys)]
(if (and preference (if (and preference
(fetch preference cofx)) (fetch cofx preference))
preference preference
(if current-id (if current-id
(round-robin choices current-id) (round-robin choices current-id)
@ -95,21 +96,27 @@
(def default? (comp not :user-defined fetch)) (def default? (comp not :user-defined fetch))
(defn delete [id {:keys [db] :as cofx}] (fx/defn delete
[{:keys [db] :as cofx} id]
(merge (when-not (or (merge (when-not (or
(default? id cofx) (default? cofx id)
(connected? id cofx)) (connected? cofx id))
{:db (update-in db [:inbox/wnodes (fleet/current-fleet db)] dissoc id) {:db (update-in db [:inbox/wnodes (fleet/current-fleet db)] dissoc id)
:data-store/tx [(data-store.mailservers/delete-tx id)]}) :data-store/tx [(data-store.mailservers/delete-tx id)]})
{:dispatch [:navigate-back]})) {:dispatch [:navigate-back]}))
(defn set-current-mailserver [{:keys [db] :as cofx}] (fx/defn set-current-mailserver
{:db (assoc db :inbox/current-id (selected-or-random-id cofx))}) [{:keys [db] :as cofx}]
{:db (assoc db :inbox/current-id
(selected-or-random-id cofx))})
(defn set-initial-last-request [{:keys [db now] :as cofx}] (fx/defn set-initial-last-request
{:db (update-in db [:account/account :last-request] (fnil identity (quot now 1000)))}) [{:keys [db now] :as cofx}]
{:db (update-in db [:account/account :last-request]
(fnil identity (quot now 1000)))})
(defn add-custom-mailservers [mailservers {:keys [db]}] (fx/defn add-custom-mailservers
[{:keys [db]} mailservers]
{:db (reduce (fn [db {:keys [id fleet] :as mailserver}] {:db (reduce (fn [db {:keys [id fleet] :as mailserver}]
(assoc-in db [:inbox/wnodes fleet id] (assoc-in db [:inbox/wnodes fleet id]
(-> mailserver (-> mailserver
@ -118,20 +125,20 @@
db db
mailservers)}) mailservers)})
(defn edit [id {:keys [db] :as cofx}] (fx/defn edit [{:keys [db] :as cofx} id]
(let [{:keys [id (let [{:keys [id
address address
password password
name]} (fetch id cofx) name]} (fetch cofx id)
url (when address (build-url address password)) url (when address (build-url address password))]
fxs (handlers-macro/merge-fx (fx/merge cofx
cofx (set-input :id id)
(set-input :id id) (set-input :url (str url))
(set-input :url (str url)) (set-input :name (str name))
(set-input :name (str name)))] (navigation/navigate-to-cofx :edit-mailserver nil))))
(assoc fxs :dispatch [:navigate-to :edit-mailserver])))
(defn upsert [{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx}] (fx/defn upsert
[{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx}]
(let [{:keys [name url id]} manage (let [{:keys [name url id]} manage
current-fleet (fleet/current-fleet db) current-fleet (fleet/current-fleet db)
mailserver (build mailserver (build
@ -139,7 +146,7 @@
(keyword (string/replace (:random-id cofx) "-" ""))) (keyword (string/replace (:random-id cofx) "-" "")))
(:value name) (:value name)
(:value url)) (:value url))
current (connected? (:id mailserver) cofx)] current (connected? cofx (:id mailserver))]
{:db (-> db {:db (-> db
(dissoc :mailservers/manage) (dissoc :mailservers/manage)
(assoc-in [:inbox/wnodes current-fleet (:id mailserver)] mailserver)) (assoc-in [:inbox/wnodes current-fleet (:id mailserver)] mailserver))
@ -152,8 +159,8 @@
:success-event (when current [:accounts.logout.ui/logout-confirmed])}] :success-event (when current [:accounts.logout.ui/logout-confirmed])}]
:dispatch [:navigate-back]})) :dispatch [:navigate-back]}))
(defn show-connection-confirmation (fx/defn show-connection-confirmation
[mailserver-id {:keys [db]}] [{:keys [db]} mailserver-id]
(let [current-fleet (fleet/current-fleet db)] (let [current-fleet (fleet/current-fleet db)]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :t/close-app-title) {:title (i18n/label :t/close-app-title)
@ -163,23 +170,22 @@
:on-accept #(re-frame/dispatch [:mailserver.ui/connect-confirmed current-fleet mailserver-id]) :on-accept #(re-frame/dispatch [:mailserver.ui/connect-confirmed current-fleet mailserver-id])
:on-cancel nil}})) :on-cancel nil}}))
(defn show-delete-confirmation (fx/defn show-delete-confirmation
[mailserver-id {:keys [db]}] [{:keys [db]} mailserver-id]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :t/delete-mailserver-title) {:title (i18n/label :t/delete-mailserver-title)
:content (i18n/label :t/delete-mailserver-are-you-sure) :content (i18n/label :t/delete-mailserver-are-you-sure)
:confirm-button-text (i18n/label :t/delete-mailserver) :confirm-button-text (i18n/label :t/delete-mailserver)
:on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}}) :on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}})
(defn save-settings (fx/defn save-settings
[current-fleet mailserver-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} current-fleet mailserver-id]
(let [settings (get-in db [:account/account :settings])] (let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx (accounts.update/update-settings cofx
(accounts.update/update-settings (assoc-in settings [:wnode current-fleet] mailserver-id)
(assoc-in settings [:wnode current-fleet] mailserver-id) {:success-event [:accounts.update.callback/save-settings-success]})))
[:accounts.update.callback/save-settings-success]))))
(defn set-url-from-qr (fx/defn set-url-from-qr
[url cofx] [cofx url]
(assoc (set-input :url url cofx) (assoc (set-input :url url cofx)
:dispatch [:navigate-back])) :dispatch [:navigate-back]))

View File

@ -3,7 +3,7 @@
[status-im.transport.message.core :as transport] [status-im.transport.message.core :as transport]
[status-im.transport.message.v1.contact :as message.v1.contact] [status-im.transport.message.v1.contact :as message.v1.contact]
[status-im.utils.contacts :as utils.contacts] [status-im.utils.contacts :as utils.contacts]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn can-add-to-contacts? [{:keys [pending? dapp?]}] (defn can-add-to-contacts? [{:keys [pending? dapp?]}]
(and (not dapp?) (and (not dapp?)
@ -24,7 +24,7 @@
:address address :address address
:fcm-token fcm-token})) :fcm-token fcm-token}))
(defn- add-new-contact [{:keys [whisper-identity] :as contact} {:keys [db]}] (fx/defn add-new-contact [{:keys [db]} {:keys [whisper-identity] :as contact}]
(let [new-contact (assoc contact (let [new-contact (assoc contact
:pending? false :pending? false
:hide-contact? false :hide-contact? false
@ -35,17 +35,18 @@
(assoc-in [:contacts/new-identity] "")) (assoc-in [:contacts/new-identity] ""))
:data-store/tx [(contacts-store/save-contact-tx new-contact)]})) :data-store/tx [(contacts-store/save-contact-tx new-contact)]}))
(defn send-contact-request [{:keys [whisper-identity pending? dapp?] :as contact} {:keys [db] :as cofx}] (fx/defn send-contact-request
[{:keys [db] :as cofx} {:keys [whisper-identity pending? dapp?] :as contact}]
(when-not dapp? (when-not dapp?
(if pending? (if pending?
(transport/send (message.v1.contact/map->ContactRequestConfirmed (own-info db)) whisper-identity cofx) (transport/send (message.v1.contact/map->ContactRequestConfirmed (own-info db)) whisper-identity cofx)
(transport/send (message.v1.contact/map->ContactRequest (own-info db)) whisper-identity cofx)))) (transport/send (message.v1.contact/map->ContactRequest (own-info db)) whisper-identity cofx))))
(defn add-contact [whisper-id {:keys [db] :as cofx}] (fx/defn add-contact [{:keys [db] :as cofx} whisper-id]
(let [contact (build-contact whisper-id cofx)] (let [contact (build-contact whisper-id cofx)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(add-new-contact contact) (add-new-contact contact)
(send-contact-request contact)))) (send-contact-request contact))))
(defn handle-contact-update (defn handle-contact-update
[public-key [public-key
@ -76,18 +77,17 @@
(:address contact) (:address contact)
(utils.contacts/public-key->address public-key)) (utils.contacts/public-key->address public-key))
:last-updated timestamp-ms :last-updated timestamp-ms
;;NOTE (yenda) in case of concurrent contact request ;;NOTE (yenda) in case of concurrent contact request
:pending? (get contact :pending? true)} :pending? (get contact :pending? true)}
fcm-token (assoc :fcm-token fcm-token))] fcm-token (assoc :fcm-token fcm-token))]
;;NOTE (yenda) only update if there is changes to the contact ;;NOTE (yenda) only update if there is changes to the contact
(when-not (= contact-props (when-not (= contact-props
(select-keys contact [:whisper-identity :public-key :address (select-keys contact [:whisper-identity :public-key :address
:photo-path :name :fcm-token :pending?])) :photo-path :name :fcm-token :pending?]))
(handlers-macro/merge-fx cofx {:db (update-in db [:contacts/contacts public-key]
{:db (update-in db [:contacts/contacts public-key] merge contact-props)
merge contact-props) :data-store/tx [(contacts-store/save-contact-tx
:data-store/tx [(contacts-store/save-contact-tx contact-props)]})))))
contact-props)]}))))))
(def receive-contact-request handle-contact-update) (def receive-contact-request handle-contact-update)
(def receive-contact-request-confirmation handle-contact-update) (def receive-contact-request-confirmation handle-contact-update)

View File

@ -1,6 +1,7 @@
(ns status-im.models.contacts) (ns status-im.models.contacts
(:require [status-im.utils.fx :as fx]))
(defn load-contacts (fx/defn load-contacts
[{:keys [db all-contacts]}] [{:keys [db all-contacts]}]
(let [contacts-list (map #(vector (:whisper-identity %) %) all-contacts) (let [contacts-list (map #(vector (:whisper-identity %) %) all-contacts)
contacts (into {} contacts-list)] contacts (into {} contacts-list)]

View File

@ -2,13 +2,11 @@
(:require [clojure.string :as string] (:require [clojure.string :as string]
[status-im.browser.core :as browser] [status-im.browser.core :as browser]
[status-im.network.core :as network] [status-im.network.core :as network]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn start-if-needed (defn start
[{{:account/keys [account]} :db}] []
(let [{:keys [dev-mode?]} account] {:dev-server/start nil})
(when dev-mode?
{:dev-server/start nil})))
;; Specific server operations ;; Specific server operations
@ -20,9 +18,9 @@
(defmethod process-request! [:POST "dapp" "open"] (defmethod process-request! [:POST "dapp" "open"]
[{{:keys [url]} :data cofx :cofx}] [{{:keys [url]} :data cofx :cofx}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:dev-server/respond [200 {:message "URL has been opened."}]} {:dev-server/respond [200 {:message "URL has been opened."}]}
(browser/open-url url))) (browser/open-url url)))
(defmethod process-request! [:POST "network" nil] (defmethod process-request! [:POST "network" nil]
[{:keys [cofx data]}] [{:keys [cofx data]}]

View File

@ -3,9 +3,9 @@
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.semaphores :as semaphores] [status-im.utils.semaphores :as semaphores]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(def sync-interval-ms 15000) (def sync-interval-ms 15000)
(def confirmations-count-threshold 12) (def confirmations-count-threshold 12)
@ -32,7 +32,7 @@
chat-transactions chat-transactions
(wallet-transactions-set db)))))) (wallet-transactions-set db))))))
(defn- schedule-sync [cofx] (fx/defn schedule-sync [cofx]
{:utils/dispatch-later [{:ms sync-interval-ms {:utils/dispatch-later [{:ms sync-interval-ms
:dispatch [:sync-wallet-transactions]}]}) :dispatch [:sync-wallet-transactions]}]})
@ -55,7 +55,7 @@
chat-transactions chat-transactions
(wallet-transactions-set db)))) (wallet-transactions-set db))))
(defn load-missing-chat-transactions (fx/defn load-missing-chat-transactions
"Find missing chat transactions and store them at [:wallet :chat-transactions] "Find missing chat transactions and store them at [:wallet :chat-transactions]
to be used later by have-missing-chat-transactions? on every sync request" to be used later by have-missing-chat-transactions? on every sync request"
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -64,7 +64,7 @@
[:wallet :chat-transactions] [:wallet :chat-transactions]
(missing-chat-transactions cofx))})) (missing-chat-transactions cofx))}))
(defn run-update [{{:keys [network network-status web3] :as db} :db}] (fx/defn run-update [{{:keys [network network-status web3] :as db} :db}]
(when (not= network-status :offline) (when (not= network-status :offline)
(let [network (get-in db [:account/account :networks network]) (let [network (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network)] chain (ethereum/network->chain-keyword network)]
@ -89,7 +89,7 @@
(< sync-interval-ms (< sync-interval-ms
(- (time/timestamp) last-updated-at))))) (- (time/timestamp) last-updated-at)))))
(defn sync (fx/defn sync
"Fetch updated data for any unconfirmed transactions or incoming chat transactions missing in wallet "Fetch updated data for any unconfirmed transactions or incoming chat transactions missing in wallet
and schedule new recurring sync request" and schedule new recurring sync request"
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -102,15 +102,15 @@
(time-to-sync? cofx) (time-to-sync? cofx)
(or (have-unconfirmed-transactions? cofx) (or (have-unconfirmed-transactions? cofx)
(have-missing-chat-transactions? cofx))) (have-missing-chat-transactions? cofx)))
(handlers-macro/merge-fx cofx (fx/merge cofx
(run-update) (run-update)
(schedule-sync)) (schedule-sync))
(schedule-sync cofx))) (schedule-sync cofx)))
{:db (semaphores/free :sync-wallet-transactions? cofx)})) (semaphores/free cofx :sync-wallet-transactions?)))
(defn start-sync [cofx] (fx/defn start-sync [cofx]
(when-not (semaphores/locked? :sync-wallet-transactions? cofx) (when-not (semaphores/locked? cofx :sync-wallet-transactions?)
(handlers-macro/merge-fx cofx (fx/merge cofx
(load-missing-chat-transactions) (load-missing-chat-transactions)
(semaphores/lock :sync-wallet-transactions?) (semaphores/lock :sync-wallet-transactions?)
(sync)))) (sync))))

View File

@ -7,7 +7,8 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.hex :as utils.hex] [status-im.utils.hex :as utils.hex]
[status-im.utils.money :as money])) [status-im.utils.money :as money]
[status-im.utils.fx :as fx]))
(def min-gas-price-wei (money/bignumber 1)) (def min-gas-price-wei (money/bignumber 1))
@ -186,7 +187,7 @@
(defn tokens-symbols [v chain] (defn tokens-symbols [v chain]
(set/difference (set v) (set (map :symbol (tokens/nfts-for chain))))) (set/difference (set v) (set (map :symbol (tokens/nfts-for chain)))))
(defn update-wallet (fx/defn update-wallet
[{{:keys [web3 network network-status] {:keys [address settings]} :account/account :as db} :db}] [{{:keys [web3 network network-status] {:keys [address settings]} :account/account :as db} :db}]
(let [network (get-in db [:account/account :networks network]) (let [network (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network) chain (ethereum/network->chain-keyword network)

View File

@ -7,7 +7,7 @@
[status-im.network.net-info :as net-info] [status-im.network.net-info :as net-info]
[status-im.transport.inbox :as inbox] [status-im.transport.inbox :as inbox]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(def url-regex (def url-regex
#"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)") #"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)")
@ -55,7 +55,8 @@
(let [network (get (:networks (:account/account db)) (:network db))] (let [network (get (:networks (:account/account db)) (:network db))]
(ethereum/network->chain-keyword network))) (ethereum/network->chain-keyword network)))
(defn set-input [input-key value {:keys [db]}] (fx/defn set-input
[{:keys [db]} input-key value]
{:db (-> db {:db (-> db
(update-in [:networks/manage input-key] assoc :value value) (update-in [:networks/manage input-key] assoc :value value)
(update-in [:networks/manage] validate-manage))}) (update-in [:networks/manage] validate-manage))})
@ -82,85 +83,84 @@
(:value chain) (:value chain)
(:value network-id)) (:value network-id))
new-networks (merge {(:id network) network} (:networks account))] new-networks (merge {(:id network) network} (:networks account))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (dissoc db :networks/manage)} {:db (dissoc db :networks/manage)}
(action-handler on-success (:id network)) #(action-handler on-success (:id network) %)
(accounts.update/account-update (accounts.update/account-update
{:networks new-networks} {:networks new-networks}
success-event))) {:success-event success-event})))
(action-handler on-failure))))) (action-handler on-failure)))))
;; No edit functionality actually implemented ;; No edit functionality actually implemented
(defn edit [{db :db}] (fx/defn edit
[{db :db}]
{:db (assoc db :networks/manage (validate-manage default-manage)) {:db (assoc db :networks/manage (validate-manage default-manage))
:dispatch [:navigate-to :edit-network]}) :dispatch [:navigate-to :edit-network]})
(defn connect [{:keys [db now] :as cofx} {:keys [network on-success on-failure]}] (fx/defn connect [{:keys [db now] :as cofx} {:keys [network on-success on-failure]}]
(if (get-in db [:account/account :networks network]) (if (get-in db [:account/account :networks network])
(let [current-network (get-in db [:account/account :networks (:network db)])] (let [current-network (get-in db [:account/account :networks (:network db)])]
(if (ethereum/network-with-upstream-rpc? current-network) (if (ethereum/network-with-upstream-rpc? current-network)
(handlers-macro/merge-fx cofx (fx/merge cofx
(action-handler on-success network) #(action-handler on-success network %)
(accounts.update/account-update (accounts.update/account-update
{:network network {:network network
:last-updated now} :last-updated now}
[:accounts.update.callback/save-settings-success])) {:success-event [:accounts.update.callback/save-settings-success]}))
(handlers-macro/merge-fx cofx (fx/merge cofx
{:ui/show-confirmation {:title (i18n/label :t/close-app-title) {:ui/show-confirmation {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/close-app-content) :content (i18n/label :t/close-app-content)
:confirm-button-text (i18n/label :t/close-app-button) :confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(re-frame/dispatch [:network.ui/save-non-rpc-network-pressed network]) :on-accept #(re-frame/dispatch [:network.ui/save-non-rpc-network-pressed network])
:on-cancel nil}} :on-cancel nil}}
(action-handler on-success network)))) #(action-handler on-success network %))))
(action-handler on-failure))) (action-handler on-failure)))
(defn delete [{{:account/keys [account]} :db :as cofx} {:keys [network on-success on-failure]}] (fx/defn delete
[{{:account/keys [account]} :db :as cofx} {:keys [network on-success on-failure]}]
(let [current-network? (= (:network account) network)] (let [current-network? (= (:network account) network)]
(if (or current-network? (if (or current-network?
(not (get-in account [:networks network]))) (not (get-in account [:networks network])))
(handlers-macro/merge-fx cofx (fx/merge cofx
{:ui/show-error (i18n/label :t/delete-network-error)} {:ui/show-error (i18n/label :t/delete-network-error)}
(action-handler on-failure network)) #(action-handler on-failure network %))
(handlers-macro/merge-fx cofx (fx/merge cofx
{:ui/show-confirmation {:title (i18n/label :t/delete-network-title) {:ui/show-confirmation {:title (i18n/label :t/delete-network-title)
:content (i18n/label :t/delete-network-confirmation) :content (i18n/label :t/delete-network-confirmation)
:confirm-button-text (i18n/label :t/delete) :confirm-button-text (i18n/label :t/delete)
:on-accept #(re-frame/dispatch [:network.ui/remove-network-confirmed network]) :on-accept #(re-frame/dispatch [:network.ui/remove-network-confirmed network])
:on-cancel nil}} :on-cancel nil}}
(action-handler on-success network))))) #(action-handler on-success network %)))))
(defn save-non-rpc-network (fx/defn save-non-rpc-network
[network {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} network]
(handlers-macro/merge-fx cofx (accounts.update/account-update cofx
(accounts.update/account-update {:network network
{:network network :last-updated now}
:last-updated now} {:success-event [:network.callback/non-rpc-network-saved]}))
[:network.callback/non-rpc-network-saved])))
(defn remove-network (fx/defn remove-network
[network {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} network]
(let [networks (dissoc (get-in db [:account/account :networks]) network)] (let [networks (dissoc (get-in db [:account/account :networks]) network)]
(handlers-macro/merge-fx cofx (accounts.update/account-update cofx
(accounts.update/account-update {:networks networks
{:networks networks :last-updated now}
:last-updated now} {:success-event [:navigate-back]})))
[:navigate-back]))))
(defn save-network (fx/defn save-network
[cofx] [cofx]
(save cofx (save cofx
{:data (get-in cofx [:db :networks/manage]) {:data (get-in cofx [:db :networks/manage])
:success-event [:navigate-back]})) :success-event [:navigate-back]}))
(defn handle-connection-status-change (fx/defn handle-connection-status-change
[is-connected? {:keys [db] :as cofx}] [{:keys [db] :as cofx} is-connected?]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (assoc db :network-status (if is-connected? :online :offline))}
{:db (assoc db :network-status (if is-connected? :online :offline))} (inbox/request-messages)))
(inbox/request-messages)))
(defn handle-network-status-change (fx/defn handle-network-status-change
[data cofx] [cofx data]
{:network/notify-status-go data}) {:network/notify-status-go data})
(re-frame/reg-fx (re-frame/reg-fx

View File

@ -5,7 +5,8 @@
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.platform :as utils.platform] [status-im.utils.platform :as utils.platform]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn- add-custom-bootnodes [config network all-bootnodes] (defn- add-custom-bootnodes [config network all-bootnodes]
(let [bootnodes (as-> all-bootnodes $ (let [bootnodes (as-> all-bootnodes $
@ -112,27 +113,25 @@
(assoc :NoDiscovery true) (assoc :NoDiscovery true)
(add-log-level config/log-level-status-go))) (add-log-level config/log-level-status-go)))
(defn start (fx/defn start
([cofx] [{:keys [db]} address]
(start nil cofx)) (let [network (if address
([address {:keys [db]}] (get-account-network db address)
(let [network (if address (:network db))
(get-account-network db address) node-config (if address
(:network db)) (get-account-node-config db address)
node-config (if address (get-node-config db network))
(get-account-node-config db address) node-config-json (types/clj->json node-config)]
(get-node-config db network)) (log/info "Node config: " node-config-json)
node-config-json (types/clj->json node-config)] {:db (assoc db :network network)
(log/info "Node config: " node-config-json) :node/start node-config-json}))
{:db (assoc db :network network)
:node/start node-config-json})))
(defn restart (defn restart
[] []
{:node/stop nil}) {:node/stop nil})
(defn initialize (fx/defn initialize
[address {{:keys [status-node-started?] :as db} :db :as cofx}] [{{:keys [status-node-started?] :as db} :db :as cofx} address]
(if (not status-node-started?) (if (not status-node-started?)
(start address cofx) (start address cofx)
(restart))) (restart)))

View File

@ -5,7 +5,7 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
;; Work in progress namespace responsible for push notifications and interacting ;; Work in progress namespace responsible for push notifications and interacting
;; with Firebase Cloud Messaging. ;; with Firebase Cloud Messaging.
@ -73,7 +73,7 @@
(then #(log/debug "Notification channel created:" channel-id) (then #(log/debug "Notification channel created:" channel-id)
#(log/error "Notification channel creation error:" channel-id %))))) #(log/error "Notification channel creation error:" channel-id %)))))
(defn store-event [{:keys [from to]} {:keys [db] :as cofx}] (fx/defn store-event [{:keys [from to]} {:keys [db] :as cofx}]
(let [{:keys [address photo-path name]} (->> (get-in cofx [:db :accounts/accounts]) (let [{:keys [address photo-path name]} (->> (get-in cofx [:db :accounts/accounts])
vals vals
(filter #(= (:public-key %) to)) (filter #(= (:public-key %) to))
@ -82,15 +82,16 @@
{:db (assoc-in db [:push-notifications/stored to] from) {:db (assoc-in db [:push-notifications/stored to] from)
:dispatch [:notifications.callback/notification-stored address photo-path name]}))) :dispatch [:notifications.callback/notification-stored address photo-path name]})))
(defn handle-push-notification [{:keys [from to] :as event} {:keys [db] :as cofx}] (fx/defn handle-push-notification
[{:keys [db] :as cofx} {:keys [from to] :as event}]
(let [current-public-key (get-in cofx [:db :current-public-key])] (let [current-public-key (get-in cofx [:db :current-public-key])]
(if current-public-key (if current-public-key
;; TODO(yenda) why do we ignore the notification if ;; TODO(yenda) why do we ignore the notification if
;; it is not for the current account ? ;; it is not for the current account ?
(when (= to current-public-key) (when (= to current-public-key)
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (update db :push-notifications/stored dissoc to)} {:db (update db :push-notifications/stored dissoc to)}
(chat-model/navigate-to-chat from nil))) (chat-model/navigate-to-chat from nil)))
(store-event event cofx)))) (store-event event cofx))))
(defn parse-notification-payload [s] (defn parse-notification-payload [s]
@ -150,14 +151,14 @@
(then #(log/debug "Display Notification" title body)) (then #(log/debug "Display Notification" title body))
(then #(log/debug "Display Notification error" title body)))))) (then #(log/debug "Display Notification error" title body))))))
(defn process-stored-event [address cofx] (fx/defn process-stored-event [cofx address]
(when-not platform/desktop? (when-not platform/desktop?
(let [to (get-in cofx [:db :accounts/accounts address :public-key]) (let [to (get-in cofx [:db :accounts/accounts address :public-key])
from (get-in cofx [:db :push-notifications/stored to])] from (get-in cofx [:db :push-notifications/stored to])]
(when from (when from
(handle-push-notification {:from from (handle-push-notification cofx
:to to} {:from from
cofx))))) :to to})))))
(re-frame/reg-fx (re-frame/reg-fx
:notifications/display-notification :notifications/display-notification

View File

@ -1,6 +1,7 @@
(ns status-im.privacy-policy.core (ns status-im.privacy-policy.core
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.ui.components.react :as react])) [status-im.ui.components.react :as react]
[status-im.utils.fx :as fx]))
(def ^:const privacy-policy-link "https://www.iubenda.com/privacy-policy/45710059") (def ^:const privacy-policy-link "https://www.iubenda.com/privacy-policy/45710059")
@ -12,5 +13,5 @@
(fn [] (fn []
(open-privacy-policy-link!))) (open-privacy-policy-link!)))
(defn open-privacy-policy-link [] (fx/defn open-privacy-policy-link [_]
{:privacy-policy/open-privacy-policy-link nil}) {:privacy-policy/open-privacy-policy-link nil})

View File

@ -4,11 +4,11 @@
[status-im.transport.core :as transport] [status-im.transport.core :as transport]
[status-im.transport.inbox :as transport.inbox] [status-im.transport.inbox :as transport.inbox]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.semaphores :as semaphores] [status-im.utils.semaphores :as semaphores]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]))
(defn update-sync-state (fx/defn update-sync-state
[{{:keys [sync-state sync-data] :as db} :db} error sync] [{{:keys [sync-state sync-data] :as db} :db} error sync]
(let [{:keys [highestBlock currentBlock] :as state} (let [{:keys [highestBlock currentBlock] :as state}
(js->clj sync :keywordize-keys true) (js->clj sync :keywordize-keys true)
@ -28,36 +28,37 @@
(not= sync-state new-state) (not= sync-state new-state)
(assoc :sync-state new-state))})) (assoc :sync-state new-state))}))
(defn check-sync-state (fx/defn check-sync-state
[{{:keys [web3] :as db} :db :as cofx}] [{{:keys [web3] :as db} :db :as cofx}]
(if (:account/account db) (if (:account/account db)
{:web3/get-syncing web3 {:web3/get-syncing web3
:dispatch-later [{:ms 10000 :dispatch [:protocol/state-sync-timed-out]}]} :dispatch-later [{:ms 10000 :dispatch [:protocol/state-sync-timed-out]}]}
(semaphores/free :check-sync-state? cofx))) (semaphores/free cofx :check-sync-state?)))
(defn start-check-sync-state (fx/defn start-check-sync-state
[{{:keys [network account/account] :as db} :db :as cofx}] [{{:keys [network account/account] :as db} :db :as cofx}]
(when (and (not (semaphores/locked? :check-sync-state? cofx)) (when (and (not (semaphores/locked? cofx :check-sync-state?))
(not (ethereum/network-with-upstream-rpc? (get-in account [:networks network])))) (not (ethereum/network-with-upstream-rpc? (get-in account [:networks network]))))
(handlers-macro/merge-fx cofx (fx/merge cofx
(check-sync-state) (check-sync-state)
(semaphores/lock :check-sync-state?)))) (semaphores/lock :check-sync-state?))))
(defn initialize-protocol (fx/defn initialize-protocol
[address {:data-store/keys [transport mailservers] :keys [db web3] :as cofx}] [{:data-store/keys [transport mailservers] :keys [db web3] :as cofx} address]
(let [network (get-in db [:account/account :network]) (let [network (get-in db [:account/account :network])
network-id (str (get-in db [:account/account :networks network :config :NetworkId]))] network-id (str (get-in db [:account/account :networks network :config :NetworkId]))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db {:db (assoc db
:rpc-url constants/ethereum-rpc-url :rpc-url constants/ethereum-rpc-url
:transport/chats transport) :transport/chats transport)
:protocol/assert-correct-network {:web3 web3 :protocol/assert-correct-network {:web3 web3
:network-id network-id}} :network-id network-id}}
(start-check-sync-state) (start-check-sync-state)
(transport.inbox/initialize-offline-inbox mailservers) (transport.inbox/initialize-offline-inbox mailservers)
(transport/init-whisper address)))) (transport/init-whisper address))))
(defn handle-close-app-confirmed [] (fx/defn handle-close-app-confirmed
[_]
{:ui/close-application nil}) {:ui/close-application nil})
(re-frame/reg-fx (re-frame/reg-fx

View File

@ -1,10 +1,11 @@
(ns status-im.qr-scanner.core (ns status-im.qr-scanner.core
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]))
(defn scan-qr-code (fx/defn scan-qr-code
[{:keys [modal?] :as identifier} qr-codes {:keys [db]}] [{:keys [db]} {:keys [modal?] :as identifier} qr-codes]
{:db (assoc db :qr-codes qr-codes) {:db (assoc db :qr-codes qr-codes)
:request-permissions-fx {:permissions [:camera] :request-permissions-fx {:permissions [:camera]
:on-allowed #(re-frame/dispatch [(if modal? :navigate-to-modal :navigate-to) :on-allowed #(re-frame/dispatch [(if modal? :navigate-to-modal :navigate-to)
@ -15,8 +16,8 @@
(i18n/label :t/camera-access-error)) (i18n/label :t/camera-access-error))
50))}}) 50))}})
(defn set-qr-code (fx/defn set-qr-code
[context data {:keys [db]}] [{:keys [db]} context data]
(merge {:db (-> db (merge {:db (-> db
(update :qr-codes dissoc context) (update :qr-codes dissoc context)
(dissoc :current-qr-context))} (dissoc :current-qr-context))}

View File

@ -5,45 +5,45 @@
[status-im.node.core :as node] [status-im.node.core :as node]
[status-im.transport.handlers :as transport.handlers] [status-im.transport.handlers :as transport.handlers]
[status-im.transport.inbox :as inbox] [status-im.transport.inbox :as inbox]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn status-node-started (fx/defn status-node-started
[{db :db :as cofx}] [{db :db :as cofx}]
(let [fx {:db (assoc db :status-node-started? true)}] (fx/merge cofx
(if (:password (accounts.db/credentials cofx)) {:db (assoc db :status-node-started? true)}
(handlers-macro/merge-fx cofx #(when (:password (accounts.db/credentials cofx))
fx (accounts.login/login %))))
(accounts.login/login))
fx)))
(defn status-node-stopped (fx/defn status-node-stopped
[cofx] [cofx]
(let [{:keys [address]} (accounts.db/credentials cofx)] (let [{:keys [address]} (accounts.db/credentials cofx)]
(node/start address cofx))) (node/start cofx address)))
(defn status-module-initialized [{:keys [db]}] (fx/defn status-module-initialized [{:keys [db]}]
{:db (assoc db :status-module-initialized? true) {:db (assoc db :status-module-initialized? true)
:init/status-module-initialized nil}) :init/status-module-initialized nil})
(defn summary [peers-summary {:keys [db] :as cofx}] (fx/defn summary
[{:keys [db] :as cofx} peers-summary]
(let [previous-summary (:peers-summary db) (let [previous-summary (:peers-summary db)
peers-count (count peers-summary)] peers-count (count peers-summary)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db {:db (assoc db
:peers-summary peers-summary :peers-summary peers-summary
:peers-count peers-count)} :peers-count peers-count)}
(transport.handlers/resend-contact-messages previous-summary) (transport.handlers/resend-contact-messages previous-summary)
(inbox/peers-summary-change-fx previous-summary)))) (inbox/peers-summary-change previous-summary))))
(defn process [event-str cofx] (fx/defn process
[cofx event-str]
(let [{:keys [type event]} (types/json->clj event-str)] (let [{:keys [type event]} (types/json->clj event-str)]
(case type (case type
"node.started" (status-node-started cofx) "node.started" (status-node-started cofx)
"node.stopped" (status-node-stopped cofx) "node.stopped" (status-node-stopped cofx)
"module.initialized" (status-module-initialized cofx) "module.initialized" (status-module-initialized cofx)
"envelope.sent" (transport.handlers/update-envelope-status (:hash event) :sent cofx) "envelope.sent" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
"envelope.expired" (transport.handlers/update-envelope-status (:hash event) :sent cofx) "envelope.expired" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
"discovery.summary" (summary event cofx) "discovery.summary" (summary cofx event)
(log/debug "Event " type " not handled")))) (log/debug "Event " type " not handled"))))

View File

@ -8,15 +8,15 @@
[status-im.transport.inbox :as inbox] [status-im.transport.inbox :as inbox]
[status-im.transport.utils :as transport.utils] [status-im.transport.utils :as transport.utils]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro] [taoensso.timbre :as log]
[taoensso.timbre :as log])) [status-im.utils.fx :as fx]))
(defn init-whisper (fx/defn init-whisper
"Initialises whisper protocol by: "Initialises whisper protocol by:
- adding fixed shh discovery filter - adding fixed shh discovery filter
- restoring existing symetric keys along with their unique filters - restoring existing symetric keys along with their unique filters
- (optionally) initializing offline inboxing" - (optionally) initializing offline inboxing"
[current-account-id {:keys [db web3] :as cofx}] [{:keys [db web3] :as cofx} current-account-id]
(log/debug :init-whisper) (log/debug :init-whisper)
(when-let [public-key (get-in db [:account/account :public-key])] (when-let [public-key (get-in db [:account/account :public-key])]
(let [sym-key-added-callback (fn [chat-id sym-key sym-key-id] (let [sym-key-added-callback (fn [chat-id sym-key sym-key-id]
@ -24,15 +24,15 @@
:sym-key sym-key :sym-key sym-key
:sym-key-id sym-key-id}])) :sym-key-id sym-key-id}]))
topic (transport.utils/get-topic constants/contact-discovery)] topic (transport.utils/get-topic constants/contact-discovery)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:shh/add-discovery-filter {:web3 web3 {:shh/add-discovery-filter {:web3 web3
:private-key-id public-key :private-key-id public-key
:topic topic} :topic topic}
: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/connect-to-mailserver) (inbox/connect-to-mailserver)
(transport.handlers/resend-contact-messages))))) (transport.handlers/resend-contact-messages [])))))
;;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,
@ -61,7 +61,7 @@
(fn [js-error js-message] (fn [js-error js-message]
(re-frame/dispatch [:protocol/receive-whisper-message js-error js-message chat-id]))))) (re-frame/dispatch [:protocol/receive-whisper-message js-error js-message chat-id])))))
(defn stop-whisper (fx/defn stop-whisper
"Stops whisper protocol by removing all existing shh filters "Stops whisper protocol by removing all existing shh filters
It is necessary to remove the filters because status-go there isn't currently a logout feature in status-go It is necessary to remove the filters because status-go there isn't currently a logout feature in status-go
to clean-up after logout. When logging out of account A and logging in account B, account B would receive to clean-up after logout. When logging out of account A and logging in account B, account B would receive

View File

@ -12,33 +12,35 @@
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.handlers-macro :as handlers-macro]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.transport.message.v1.protocol :as protocol])) [status-im.transport.message.v1.protocol :as protocol]
[status-im.utils.fx :as fx]))
(defn update-last-received-from-inbox (fx/defn update-last-received-from-inbox
"Distinguishes messages that are expired from those that are not "Distinguishes messages that are expired from those that are not
Expired messages are coming from offline inboxing" Expired messages are coming from offline inboxing"
[now-in-s timestamp ttl {:keys [db now] :as cofx}] [{:keys [db now] :as cofx} now-in-s timestamp ttl]
(when (> (- now-in-s timestamp) ttl) (when (> (- now-in-s timestamp) ttl)
{:db (assoc db :inbox/last-received now)})) {:db (assoc db :inbox/last-received now)}))
(defn receive-message [cofx now-in-s chat-id js-message] (defn receive-message
[cofx now-in-s chat-id js-message]
(let [{:keys [payload sig timestamp ttl]} (js->clj js-message :keywordize-keys true) (let [{:keys [payload sig timestamp ttl]} (js->clj js-message :keywordize-keys true)
status-message (-> payload status-message (-> payload
transport.utils/to-utf8 transport.utils/to-utf8
transit/deserialize)] transit/deserialize)]
(when (and sig status-message) (when (and sig status-message)
(try (try
(handlers-macro/merge-fx (fx/merge (assoc cofx :js-obj js-message)
(assoc cofx :js-obj js-message) #(message/receive status-message (or chat-id sig) sig timestamp %)
(message/receive status-message (or chat-id sig) sig timestamp) (update-last-received-from-inbox now-in-s timestamp ttl))
(update-last-received-from-inbox now-in-s timestamp ttl))
(catch :default e nil))))) ; ignore unknown message types (catch :default e nil))))) ; ignore unknown message types
(defn- js-array->seq [array] (defn- js-array->seq [array]
(for [i (range (.-length array))] (for [i (range (.-length array))]
(aget array i))) (aget array i)))
(defn receive-whisper-messages [{:keys [now] :as cofx} [_ js-error js-messages chat-id]] (fx/defn receive-whisper-messages
[{:keys [now] :as cofx} [_ js-error js-messages chat-id]]
(if (and (not js-error) (if (and (not js-error)
js-messages) js-messages)
(let [now-in-s (quot now 1000)] (let [now-in-s (quot now 1000)]
@ -68,16 +70,16 @@
(assoc :sym-key-id sym-key-id (assoc :sym-key-id sym-key-id
:sym-key sym-key :sym-key sym-key
:topic topic))] :topic topic))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:transport/chats chat-id] chat-transport-info) {:db (assoc-in db [:transport/chats chat-id] chat-transport-info)
: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
:chat-id chat-id} :chat-id chat-id}
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id :data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat chat-transport-info})]} :chat chat-transport-info})]}
(message/send (v1.contact/NewContactKey. sym-key topic message) #(message/send (v1.contact/NewContactKey. sym-key topic message)
chat-id))))) chat-id %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:contact/add-new-sym-key :contact/add-new-sym-key
@ -87,32 +89,18 @@
(assoc :sym-key-id sym-key-id (assoc :sym-key-id sym-key-id
:sym-key sym-key :sym-key sym-key
:topic topic))] :topic topic))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id] [:transport/chats chat-id]
chat-transport-info) chat-transport-info)
:dispatch [:inbox/request-chat-history chat-id] :dispatch [:inbox/request-chat-history chat-id]
: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
:chat-id chat-id} :chat-id chat-id}
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id :data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat chat-transport-info})]} :chat chat-transport-info})]}
(message/receive message chat-id chat-id timestamp))))) #(message/receive message chat-id chat-id timestamp %)))))
#_(handlers/register-handler-fx
:send-test-message
(fn [cofx [this timer chat-id n]]
(if (zero? n)
(println "Time: " (str (- (inst-ms (js/Date.)) @timer)))
(handlers-macro/merge-fx cofx
{:dispatch [this timer chat-id (dec n)]}
(message/send (protocol/map->Message {:content (str n)
:content-type "text/plain"
:message-type :user-message
:clock-value n
:timestamp (str (inst-ms (js/Date.)))})
chat-id)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:group/unsubscribe-from-chat :group/unsubscribe-from-chat
@ -125,22 +113,22 @@
;; some async operations ;; some async operations
(fn [{:keys [db] :as cofx} [_ {:keys [chat-id message sym-key sym-key-id]}]] (fn [{:keys [db] :as cofx} [_ {:keys [chat-id message sym-key sym-key-id]}]]
(let [{:keys [web3]} db] (let [{:keys [web3]} db]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (update-in db [:transport/chats chat-id] {:db (update-in db [:transport/chats chat-id]
assoc assoc
:sym-key-id sym-key-id :sym-key-id sym-key-id
:sym-key sym-key) :sym-key sym-key)
:shh/add-filter {:web3 web3 :shh/add-filter {:web3 web3
:sym-key-id sym-key-id :sym-key-id sym-key-id
:topic (transport.utils/get-topic chat-id) :topic (transport.utils/get-topic chat-id)
:chat-id chat-id} :chat-id chat-id}
:data-store/tx [(transport-store/save-transport-tx :data-store/tx [(transport-store/save-transport-tx
{:chat-id chat-id {:chat-id chat-id
:chat (-> (get-in db [:transport/chats chat-id]) :chat (-> (get-in db [:transport/chats chat-id])
(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))})]}
(message/send (v1.group-chat/NewGroupKey. chat-id sym-key message) chat-id))))) #(message/send (v1.group-chat/NewGroupKey. chat-id sym-key message) chat-id %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:group/add-new-sym-key :group/add-new-sym-key
@ -163,9 +151,10 @@
;;TODO (yenda) remove once go implements persistence ;;TODO (yenda) remove once go implements persistence
(assoc :sym-key sym-key))})]}] (assoc :sym-key sym-key))})]}]
;; if new sym-key is wrapping some message, call receive on it as well, if not just update the transport layer ;; if new sym-key is wrapping some message, call receive on it as well, if not just update the transport layer
(if message (fx/merge cofx
(handlers-macro/merge-fx cofx fx (message/receive message chat-id signature timestamp)) fx
fx)))) #(when message
(message/receive message chat-id signature timestamp %))))))
(re-frame/reg-fx (re-frame/reg-fx
;; TODO(janherich): this should be called after `:data-store/tx` actually ;; TODO(janherich): this should be called after `:data-store/tx` actually
@ -198,33 +187,33 @@
{:chat-id chat-id {:chat-id chat-id
:message-type :contact-message})})) :message-type :contact-message})}))
(defn remove-hash [envelope-hash {:keys [db] :as cofx}] (fx/defn remove-hash [{:keys [db] :as cofx} envelope-hash]
{:db (update db :transport/message-envelopes dissoc envelope-hash)}) {:db (update db :transport/message-envelopes dissoc envelope-hash)})
(defn update-resend-contact-message [chat-id {:keys [db] :as cofx}] (fx/defn update-resend-contact-message [{:keys [db] :as cofx} chat-id]
(let [chat (get-in db [:transport/chats chat-id]) (let [chat (get-in db [:transport/chats chat-id])
updated-chat (assoc chat :resend? nil)] updated-chat (assoc chat :resend? nil)]
{:db (assoc-in db [:transport/chats chat-id :resend?] nil) {:db (assoc-in db [:transport/chats chat-id :resend?] nil)
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id :data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]})) :chat updated-chat})]}))
(defn update-envelope-status (fx/defn update-envelope-status
[envelope-hash status {:keys [db] :as cofx}] [{:keys [db] :as cofx} envelope-hash status]
(let [{:keys [chat-id message-type message-id]} (let [{:keys [chat-id message-type message-id]}
(get-in db [:transport/message-envelopes envelope-hash])] (get-in db [:transport/message-envelopes envelope-hash])]
(case message-type (case message-type
:contact-message :contact-message
(when (= :sent status) (when (= :sent status)
(handlers-macro/merge-fx cofx (fx/merge cofx
(remove-hash envelope-hash) (remove-hash envelope-hash)
(update-resend-contact-message chat-id))) (update-resend-contact-message chat-id)))
(when-let [message (get-in db [:chats chat-id :messages message-id])] (when-let [message (get-in db [:chats chat-id :messages message-id])]
(let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])] (let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
(handlers-macro/merge-fx cofx (fx/merge cofx
(remove-hash envelope-hash) (remove-hash envelope-hash)
(models.message/update-message-status message status) (models.message/update-message-status message status)
(models.message/send-push-notification fcm-token status))))))) (models.message/send-push-notification fcm-token status)))))))
(defn- own-info [db] (defn- own-info [db]
(let [{:keys [name photo-path address]} (:account/account db) (let [{:keys [name photo-path address]} (:account/account db)
@ -234,32 +223,30 @@
:address address :address address
:fcm-token fcm-token})) :fcm-token fcm-token}))
(defn resend-contact-request [own-info chat-id {:keys [sym-key topic]} cofx] (fx/defn resend-contact-request [cofx own-info chat-id {:keys [sym-key topic]}]
(message/send (v1.contact/NewContactKey. sym-key (message/send (v1.contact/NewContactKey. sym-key
topic topic
(v1.contact/map->ContactRequest own-info)) (v1.contact/map->ContactRequest own-info))
chat-id cofx)) chat-id cofx))
(defn resend-contact-messages (fx/defn resend-contact-messages
([cofx] [{:keys [db] :as cofx} previous-summary]
(resend-contact-messages [] cofx)) (when (and (zero? (count previous-summary))
([previous-summary {:keys [db] :as cofx}] (= :online (:network-status db))
(when (and (zero? (count previous-summary)) (pos? (count (:peers-summary db))))
(= :online (:network-status db)) (let [own-info (own-info db)]
(pos? (count (:peers-summary db)))) (handlers-macro/merge-effects
(let [own-info (own-info db)] cofx
(handlers-macro/merge-effects (fn [[chat-id {:keys [resend?] :as chat}] temp-cofx]
cofx (case resend?
(fn [[chat-id {:keys [resend?] :as chat}] temp-cofx] "contact-request"
(case resend? (resend-contact-request own-info chat-id chat temp-cofx)
"contact-request" "contact-request-confirmation"
(resend-contact-request own-info chat-id chat temp-cofx) (message/send (v1.contact/map->ContactRequestConfirmed own-info)
"contact-request-confirmation" chat-id temp-cofx)
(message/send (v1.contact/map->ContactRequestConfirmed own-info) "contact-update"
chat-id temp-cofx) (protocol/send {:chat-id chat-id
"contact-update" :payload (v1.contact/map->ContactUpdate own-info)}
(protocol/send {:chat-id chat-id temp-cofx)
:payload (v1.contact/map->ContactUpdate own-info)} nil))
temp-cofx) (:transport/chats db)))))
nil))
(:transport/chats db))))))

View File

@ -1,23 +1,18 @@
(ns ^{:doc "Offline inboxing events and API"} (ns ^{:doc "Offline inboxing events and API"}
status-im.transport.inbox status-im.transport.inbox
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.native-module.core :as status]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.transport.utils :as transport.utils]
[status-im.utils.config :as config]
[taoensso.timbre :as log]
[status-im.constants :as constants]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.utils :as utils]
[status-im.i18n :as i18n]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.data-store.accounts :as accounts-store] [status-im.data-store.accounts :as accounts-store]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.data-store.core :as data-store] [status-im.data-store.core :as data-store]
[status-im.mailserver.core :as mailserver]
[status-im.data-store.transport :as transport-store] [status-im.data-store.transport :as transport-store]
[status-im.fleet.core :as fleet])) [status-im.fleet.core :as fleet]
[status-im.mailserver.core :as mailserver]
[status-im.native-module.core :as status]
[status-im.transport.utils :as transport.utils]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
;; How does offline inboxing work ? ;; How does offline inboxing work ?
;; ;;
@ -76,7 +71,8 @@
(error-fn error) (error-fn error)
(success-fn result))))) (success-fn result)))))
(defn add-sym-key-id-to-wnode [{:keys [id]} sym-key-id {:keys [db]}] (fx/defn add-sym-key-id-to-wnode
[{:keys [db]} {:keys [id]} sym-key-id]
(let [current-fleet (fleet/current-fleet db)] (let [current-fleet (fleet/current-fleet db)]
{:db (assoc-in db [:inbox/wnodes current-fleet id :sym-key-id] sym-key-id)})) {:db (assoc-in db [:inbox/wnodes current-fleet id :sym-key-id] sym-key-id)}))
@ -158,13 +154,13 @@
#(log/info "offline inbox: request-messages response" %1 %2 from to) #(log/info "offline inbox: request-messages response" %1 %2 from to)
#(log/error "offline inbox: request-messages error" %1 %2 from to))))) #(log/error "offline inbox: request-messages error" %1 %2 from to)))))
(defn update-mailserver-status [transition {:keys [db]}] (fx/defn update-mailserver-status [{:keys [db]} transition]
(let [state transition] (let [state transition]
{:db (assoc db {:db (assoc db
:mailserver-status state :mailserver-status state
:inbox/fetching? false)})) :inbox/fetching? false)}))
(defn generate-mailserver-symkey [wnode {:keys [db] :as cofx}] (fx/defn generate-mailserver-symkey [{:keys [db] :as cofx} wnode]
(when-not (:sym-key-id wnode) (when-not (:sym-key-id wnode)
{:shh/generate-sym-key-from-password {:shh/generate-sym-key-from-password
[{:password (:password wnode) [{:password (:password wnode)
@ -173,7 +169,7 @@
(re-frame/dispatch [:inbox/get-sym-key-success wnode sym-key-id])) (re-frame/dispatch [:inbox/get-sym-key-success wnode sym-key-id]))
:on-error #(log/error "offline inbox: get-sym-key error" %)}]})) :on-error #(log/error "offline inbox: get-sym-key error" %)}]}))
(defn connect-to-mailserver (fx/defn connect-to-mailserver
"Add mailserver as a peer using ::add-peer cofx and generate sym-key when "Add mailserver as a peer using ::add-peer cofx and generate sym-key when
it doesn't exists it doesn't exists
Peer summary will change and we will receive a signal from status go when Peer summary will change and we will receive a signal from status go when
@ -186,21 +182,21 @@
peers-summary (:peers-summary db) peers-summary (:peers-summary db)
connected? (registered-peer? peers-summary address)] connected? (registered-peer? peers-summary address)]
(if connected? (if connected?
(handlers-macro/merge-fx cofx (fx/merge cofx
(update-mailserver-status :connected) (update-mailserver-status :connected)
(generate-mailserver-symkey wnode)) (generate-mailserver-symkey wnode))
(handlers-macro/merge-fx cofx (fx/merge cofx
{::add-peer {:wnode address} {::add-peer {:wnode address}
:utils/dispatch-later [{:ms connection-timeout :utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/check-connection]}]} :dispatch [:inbox/check-connection]}]}
(update-mailserver-status :connecting) (update-mailserver-status :connecting)
(generate-mailserver-symkey wnode))))) (generate-mailserver-symkey wnode)))))
(defn peers-summary-change-fx (fx/defn peers-summary-change
"There is only 2 summary changes that require offline inboxing action: "There is only 2 summary changes that require offline inboxing action:
- mailserver disconnected: we try to reconnect - mailserver disconnected: we try to reconnect
- mailserver connected: we mark the mailserver as trusted peer" - mailserver connected: we mark the mailserver as trusted peer"
[previous-summary {:keys [db] :as cofx}] [{:keys [db] :as cofx} previous-summary]
(when (:account/account db) (when (:account/account db)
(let [{:keys [peers-summary peers-count]} db (let [{:keys [peers-summary peers-count]} db
wnode (:address (mailserver/fetch-current cofx)) wnode (:address (mailserver/fetch-current cofx))
@ -245,35 +241,32 @@
(defn request-history-span [now-in-s] (defn request-history-span [now-in-s]
(- now-in-s one-day)) (- now-in-s one-day))
(defn request-messages (fx/defn request-messages
([{:keys [db now] :as cofx}] [{:keys [db now] :as cofx}]
(let [wnode (mailserver/fetch-current cofx) (let [wnode (mailserver/fetch-current cofx)
web3 (:web3 db) web3 (:web3 db)
now-in-s (quot now 1000) now-in-s (quot now 1000)
last-request (max last-request (max
(get-in db [:account/account :last-request]) (get-in db [:account/account :last-request])
(- now-in-s seven-days)) (- now-in-s seven-days))
request-messages-topics (get-request-messages-topics db) request-messages-topics (get-request-messages-topics db)
request-history-topics (get-request-history-topics db)] request-history-topics (get-request-history-topics db)]
(when (inbox-ready? wnode cofx) (when (inbox-ready? wnode cofx)
{::request-messages [{:wnode wnode {::request-messages [{:wnode wnode
:topics request-messages-topics :topics request-messages-topics
:from last-request :from last-request
:to now-in-s :to now-in-s
:web3 web3} :web3 web3}
{:wnode wnode {:wnode wnode
:from (request-history-span now-in-s) :from (request-history-span now-in-s)
:to now-in-s :to now-in-s
:topics request-history-topics :topics request-history-topics
:web3 web3}] :web3 web3}]
:db (assoc db :inbox/fetching? true) :db (assoc db :inbox/fetching? true)
:dispatch-later [{:ms fetching-timeout :dispatch-later [{:ms fetching-timeout
:dispatch [:inbox/check-fetching now-in-s]}]}))) :dispatch [:inbox/check-fetching now-in-s]}]})))
([should-recover? {:keys [db] :as cofx}]
(when should-recover?
(request-messages cofx))))
(defn request-chat-history [chat-id {:keys [db now] :as cofx}] (fx/defn request-chat-history [{:keys [db now] :as cofx} chat-id]
(let [wnode (mailserver/fetch-current cofx) (let [wnode (mailserver/fetch-current cofx)
web3 (:web3 db) web3 (:web3 db)
topic (get-in db [:transport/chats chat-id :topic]) topic (get-in db [:transport/chats chat-id :topic])
@ -293,33 +286,34 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/mailserver-trusted :inbox/mailserver-trusted
(fn [{:keys [db] :as cofx} _] (fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx (fx/merge cofx
(update-mailserver-status :connected) (update-mailserver-status :connected)
(request-messages)))) (request-messages))))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/get-sym-key-success :inbox/get-sym-key-success
(fn [{:keys [db] :as cofx} [_ wnode sym-key-id]] (fn [{:keys [db] :as cofx} [_ wnode sym-key-id]]
(handlers-macro/merge-fx cofx (fx/merge cofx
(add-sym-key-id-to-wnode wnode sym-key-id) (add-sym-key-id-to-wnode wnode sym-key-id)
(request-messages)))) (request-messages))))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/request-chat-history :inbox/request-chat-history
(fn [{:keys [db] :as cofx} [_ chat-id]] (fn [{:keys [db] :as cofx} [_ chat-id]]
(request-chat-history chat-id cofx))) (request-chat-history cofx chat-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/check-connection :inbox/check-connection
(fn [{:keys [db] :as cofx} _] (fn [{:keys [db] :as cofx} _]
(when (= :connecting (:mailserver-status db)) (when (= :connecting (:mailserver-status db))
(if (mailserver/preferred-mailserver-id cofx) (if (mailserver/preferred-mailserver-id cofx)
(update-mailserver-status :error cofx) (update-mailserver-status cofx :error)
(handlers-macro/merge-fx cofx (fx/merge cofx
(mailserver/set-current-mailserver) (mailserver/set-current-mailserver)
(connect-to-mailserver)))))) (connect-to-mailserver))))))
(defn update-last-request [last-request {:keys [db]}] (fx/defn update-last-request
[{:keys [db]} last-request]
(let [chats (:transport/chats db) (let [chats (:transport/chats db)
transport-txs (reduce (fn [txs [chat-id chat]] transport-txs (reduce (fn [txs [chat-id chat]]
(if (:fetch-history? chat) (if (:fetch-history? chat)
@ -346,7 +340,7 @@
:last-request last-request))] :last-request last-request))]
:data-store/tx transport-txs})) :data-store/tx transport-txs}))
(defn update-fetch-history [chat-id {:keys [db]}] (fx/defn update-fetch-history [{:keys [db]} chat-id]
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id :fetch-history?] [:transport/chats chat-id :fetch-history?]
false) false)
@ -355,11 +349,11 @@
:chat (assoc (get-in db [:transport/chats chat-id]) :chat (assoc (get-in db [:transport/chats chat-id])
:fetch-history? false)})]}) :fetch-history? false)})]})
(defn initialize-offline-inbox [custom-mailservers cofx] (fx/defn initialize-offline-inbox [cofx custom-mailservers]
(handlers-macro/merge-fx cofx (fx/merge cofx
(mailserver/add-custom-mailservers custom-mailservers) (mailserver/add-custom-mailservers custom-mailservers)
(mailserver/set-initial-last-request) (mailserver/set-initial-last-request)
(mailserver/set-current-mailserver))) (mailserver/set-current-mailserver)))
(handlers/register-handler-fx (handlers/register-handler-fx
:inbox/check-fetching :inbox/check-fetching
@ -371,12 +365,12 @@
(let [time-since-last-received (- now (:inbox/last-received db))] (let [time-since-last-received (- now (:inbox/last-received db))]
(if (> time-since-last-received fetching-timeout) (if (> time-since-last-received fetching-timeout)
(if chat-id (if chat-id
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :inbox/fetching? false)} {:db (assoc db :inbox/fetching? false)}
(update-fetch-history chat-id)) (update-fetch-history chat-id))
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :inbox/fetching? false)} {:db (assoc db :inbox/fetching? false)}
(update-last-request last-request))) (update-last-request last-request)))
{:dispatch-later [{:ms (- fetching-timeout {:dispatch-later [{:ms (- fetching-timeout
time-since-last-received) time-since-last-received)
:dispatch [:inbox/check-fetching last-request chat-id]}]}))))) :dispatch [:inbox/check-fetching last-request chat-id]}]})))))

View File

@ -5,7 +5,8 @@
[status-im.transport.message.core :as message] [status-im.transport.message.core :as message]
[status-im.transport.message.v1.protocol :as protocol] [status-im.transport.message.v1.protocol :as protocol]
[status-im.transport.utils :as transport.utils] [status-im.transport.utils :as transport.utils]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.fx :as fx]))
(defrecord ContactRequest [name profile-image address fcm-token] (defrecord ContactRequest [name profile-image address fcm-token]
message/StatusMessage message/StatusMessage
@ -18,12 +19,12 @@
:chat-id chat-id :chat-id chat-id
:topic topic :topic topic
:message this}]))] :message this}]))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:shh/get-new-sym-keys [{:web3 (:web3 db) {:shh/get-new-sym-keys [{:web3 (:web3 db)
:on-success on-success}]} :on-success on-success}]}
(protocol/init-chat {:chat-id chat-id (protocol/init-chat {:chat-id chat-id
:topic topic :topic topic
:resend? "contact-request"}))))) :resend? "contact-request"})))))
(defrecord ContactRequestConfirmed [name profile-image address fcm-token] (defrecord ContactRequestConfirmed [name profile-image address fcm-token]
message/StatusMessage message/StatusMessage
@ -31,15 +32,15 @@
(let [success-event [:transport/set-contact-message-envelope-hash chat-id] (let [success-event [:transport/set-contact-message-envelope-hash chat-id]
chat (get-in db [:transport/chats chat-id]) chat (get-in db [:transport/chats chat-id])
updated-chat (assoc chat :resend? "contact-request-confirmation")] updated-chat (assoc chat :resend? "contact-request-confirmation")]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id :resend?] [:transport/chats chat-id :resend?]
"contact-request-confirmation") "contact-request-confirmation")
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id :data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]} :chat updated-chat})]}
(protocol/send-with-pubkey {:chat-id chat-id (protocol/send-with-pubkey {:chat-id chat-id
:payload this :payload this
:success-event success-event}))))) :success-event success-event})))))
(defrecord ContactUpdate [name profile-image address fcm-token] (defrecord ContactUpdate [name profile-image address fcm-token]
message/StatusMessage message/StatusMessage
@ -59,36 +60,37 @@
tx [(transport-store/save-transport-tx {:chat-id chat-id tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})] :chat updated-chat})]
success-event [:transport/set-contact-message-envelope-hash chat-id]] success-event [:transport/set-contact-message-envelope-hash chat-id]]
(handlers-macro/merge-fx temp-cofx (fx/merge temp-cofx
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id :resend?] [:transport/chats chat-id :resend?]
"contact-update") "contact-update")
:data-store/tx tx} :data-store/tx tx}
(protocol/send-with-pubkey {:chat-id chat-id (protocol/send-with-pubkey {:chat-id chat-id
:payload this :payload this
:success-event success-event})))) :success-event success-event}))))
recipients)))) recipients))))
(defn remove-chat-filter (fx/defn remove-chat-filter
"Stops the filter for the given chat-id" "Stops the filter for the given chat-id"
[chat-id {:keys [db]}] [{:keys [db]} chat-id]
(when-let [filter (get-in db [:transport/chats chat-id :filter])] (when-let [filter (get-in db [:transport/chats chat-id :filter])]
{:shh/remove-filter filter})) {:shh/remove-filter filter}))
(defn init-chat (fx/defn init-chat
[chat-id topic cofx] [cofx chat-id topic]
(when-not (get-in cofx [:db :transport/chats chat-id]) (when-not (get-in cofx [:db :transport/chats chat-id])
(protocol/init-chat {:chat-id chat-id (protocol/init-chat cofx
:topic topic} cofx))) {:chat-id chat-id
:topic topic})))
(defrecord NewContactKey [sym-key topic message] (defrecord NewContactKey [sym-key topic message]
message/StatusMessage message/StatusMessage
(send [this chat-id cofx] (send [this chat-id cofx]
(let [success-event [:transport/set-contact-message-envelope-hash chat-id]] (let [success-event [:transport/set-contact-message-envelope-hash chat-id]]
(protocol/send-with-pubkey {:chat-id chat-id (protocol/send-with-pubkey cofx
{:chat-id chat-id
:payload this :payload this
:success-event success-event} :success-event success-event})))
cofx)))
(receive [this chat-id _ timestamp {:keys [db] :as cofx}] (receive [this chat-id _ timestamp {:keys [db] :as cofx}]
(let [current-sym-key (get-in db [:transport/chats chat-id :sym-key]) (let [current-sym-key (get-in db [:transport/chats chat-id :sym-key])
;; NOTE(yenda) to support concurrent contact request without additional ;; NOTE(yenda) to support concurrent contact request without additional
@ -109,14 +111,14 @@
:chat-id chat-id :chat-id chat-id
:topic topic :topic topic
:message message}]))] :message message}]))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:shh/add-new-sym-keys [{:web3 (:web3 db) {:shh/add-new-sym-keys [{:web3 (:web3 db)
:sym-key sym-key :sym-key sym-key
:on-success on-success}]} :on-success on-success}]}
(init-chat chat-id topic) (init-chat chat-id topic)
;; in case of concurrent contact request we want ;; in case of concurrent contact request we want
;; to stop the filter for the previous key before ;; to stop the filter for the previous key before
;; dereferrencing it ;; dereferrencing it
(remove-chat-filter chat-id))) (remove-chat-filter chat-id)))
;; if we don't save the key, we read the message directly ;; if we don't save the key, we read the message directly
(message/receive message chat-id chat-id timestamp cofx))))) (message/receive message chat-id chat-id timestamp cofx)))))

View File

@ -1,10 +1,10 @@
(ns ^{:doc "Group chat API"} (ns ^{:doc "Group chat API"}
status-im.transport.message.v1.group-chat status-im.transport.message.v1.group-chat
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.transport.message.core :as message] [status-im.transport.message.core :as message]
[status-im.transport.message.v1.protocol :as protocol] [status-im.transport.message.v1.protocol :as protocol]
[status-im.transport.utils :as transport.utils])) [status-im.transport.utils :as transport.utils]
[status-im.utils.fx :as fx]))
;; NOTE: We ignore the chat-id from the send and receive method. ;; NOTE: We ignore the chat-id from the send and receive method.
;; The chat-id is usually deduced from the filter the message comes from but not in that case because it is sent ;; The chat-id is usually deduced from the filter the message comes from but not in that case because it is sent
@ -20,28 +20,28 @@
:payload this} :payload this}
cofx))) cofx)))
(receive [this _ signature timestamp {:keys [db] :as cofx}] (receive [this _ signature timestamp {:keys [db] :as cofx}]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:shh/add-new-sym-keys
{:shh/add-new-sym-keys [{:web3 (:web3 db)
[{:web3 (:web3 db) :sym-key sym-key
:sym-key sym-key :on-success (fn [sym-key sym-key-id]
:on-success (fn [sym-key sym-key-id] (re-frame/dispatch
(re-frame/dispatch [:group/add-new-sym-key
[:group/add-new-sym-key {:chat-id chat-id
{:chat-id chat-id :signature signature
:signature signature :timestamp timestamp
:timestamp timestamp :sym-key sym-key
:sym-key sym-key :sym-key-id sym-key-id
:sym-key-id sym-key-id :message message}]))}]}
:message message}]))}]} (protocol/init-chat {:chat-id chat-id}))))
(protocol/init-chat {:chat-id chat-id}))))
(defn- user-is-group-admin? [chat-id cofx] (defn- user-is-group-admin? [cofx chat-id]
(= (get-in cofx [:db :chats chat-id :group-admin]) (= (get-in cofx [:db :chats chat-id :group-admin])
(get-in cofx [:db :current-public-key]))) (get-in cofx [:db :current-public-key])))
(defn send-new-group-key [message chat-id cofx] (fx/defn send-new-group-key
(when (user-is-group-admin? chat-id cofx) [message chat-id cofx]
(when (user-is-group-admin? cofx chat-id)
{:shh/get-new-sym-keys [{:web3 (get-in cofx [:db :web3]) {:shh/get-new-sym-keys [{:web3 (get-in cofx [:db :web3])
:on-success (fn [sym-key sym-key-id] :on-success (fn [sym-key sym-key-id]
(re-frame/dispatch (re-frame/dispatch
@ -51,21 +51,18 @@
:sym-key-id sym-key-id :sym-key-id sym-key-id
:message message}]))}]})) :message message}]))}]}))
(defn- init-chat-if-new [chat-id cofx]
(if (nil? (get-in cofx [:db :transport/chats chat-id]))
(protocol/init-chat {:chat-id chat-id} cofx)))
(defrecord GroupAdminUpdate [chat-name participants] (defrecord GroupAdminUpdate [chat-name participants]
message/StatusMessage message/StatusMessage
(send [this chat-id cofx] (send [this chat-id cofx]
(handlers-macro/merge-fx cofx (fx/merge cofx
(init-chat-if-new chat-id) #(when (nil? (get-in % [:db :transport/chats chat-id]))
(send-new-group-key this chat-id)))) (protocol/init-chat {:chat-id chat-id} %))
(send-new-group-key this chat-id))))
(defrecord GroupLeave [] (defrecord GroupLeave []
message/StatusMessage message/StatusMessage
(send [this chat-id cofx] (send [this chat-id cofx]
(protocol/send {:chat-id chat-id (protocol/send cofx
{:chat-id chat-id
:payload this :payload this
:success-event [:group/unsubscribe-from-chat chat-id]} :success-event [:group/unsubscribe-from-chat chat-id]})))
cofx)))

View File

@ -5,33 +5,28 @@
[status-im.chat.core :as chat] [status-im.chat.core :as chat]
[status-im.transport.db :as transport.db] [status-im.transport.db :as transport.db]
[status-im.transport.message.core :as message] [status-im.transport.message.core :as message]
[status-im.transport.utils :as transport.utils])) [status-im.transport.utils :as transport.utils]
[status-im.utils.fx :as fx]))
(def ^:private whisper-opts (def ^:private whisper-opts
{:ttl 10 ;; ttl of 10 sec {:ttl 10 ;; ttl of 10 sec
:powTarget config/pow-target :powTarget config/pow-target
:powTime config/pow-time}) :powTime config/pow-time})
(defn init-chat (fx/defn init-chat
"Initialises chat on protocol layer. "Initialises chat on protocol layer.
If topic is not passed as argument it is derived from `chat-id`" If topic is not passed as argument it is derived from `chat-id`"
[{:keys [chat-id topic resend?] [{:keys [db]}
:or {topic (transport.utils/get-topic chat-id)}} {:keys [chat-id topic resend?]
{:keys [db]}] :or {topic (transport.utils/get-topic chat-id)}}]
{:db (assoc-in db {:db (assoc-in db
[:transport/chats chat-id] [:transport/chats chat-id]
(transport.db/create-chat {:topic topic (transport.db/create-chat {:topic topic
:resend? resend?}))}) :resend? resend?}))})
#_(defn requires-ack [message-id chat-id {:keys [db] :as cofx}] (fx/defn send
{:db (update-in db [:transport/chats chat-id :pending-ack] conj message-id)})
#_(defn ack [message-id chat-id {:keys [db] :as cofx}]
{:db (update-in db [:transport/chats chat-id :ack] conj message-id)})
(defn send
"Sends the payload using symetric key and topic from db (looked up by `chat-id`)" "Sends the payload using symetric key and topic from db (looked up by `chat-id`)"
[{:keys [payload chat-id success-event]} {:keys [db] :as cofx}] [{:keys [db] :as cofx} {:keys [payload chat-id success-event]}]
;; we assume that the chat contains the contact public-key ;; we assume that the chat contains the contact public-key
(let [{:keys [current-public-key web3]} db (let [{:keys [current-public-key web3]} db
{:keys [sym-key-id topic]} (get-in db [:transport/chats chat-id])] {:keys [sym-key-id topic]} (get-in db [:transport/chats chat-id])]
@ -43,9 +38,9 @@
:topic topic} :topic topic}
whisper-opts)}]})) whisper-opts)}]}))
(defn send-with-pubkey (fx/defn send-with-pubkey
"Sends the payload using asymetric key (`:current-public-key` in db) and fixed discovery topic" "Sends the payload using asymetric key (`:current-public-key` in db) and fixed discovery topic"
[{:keys [payload chat-id success-event]} {:keys [db] :as cofx}] [{:keys [db] :as cofx} {:keys [payload chat-id success-event]}]
(let [{:keys [current-public-key web3]} db] (let [{:keys [current-public-key web3]} db]
{:shh/post [{:web3 web3 {:shh/post [{:web3 web3
:success-event success-event :success-event success-event
@ -60,9 +55,9 @@
(select-keys (get-in db [:transport/chats public-key]) [:topic :sym-key-id])) (select-keys (get-in db [:transport/chats public-key]) [:topic :sym-key-id]))
public-keys)) public-keys))
(defn multi-send-by-pubkey (fx/defn multi-send-by-pubkey
"Sends payload to multiple participants selected by `:public-keys` key. " "Sends payload to multiple participants selected by `:public-keys` key. "
[{:keys [payload public-keys success-event]} {:keys [db] :as cofx}] [{:keys [db] :as cofx} {:keys [payload public-keys success-event]}]
(let [{:keys [current-public-key web3]} db (let [{:keys [current-public-key web3]} db
recipients (prepare-recipients public-keys db)] recipients (prepare-recipients public-keys db)]
{:shh/multi-post {:web3 web3 {:shh/multi-post {:web3 web3
@ -95,8 +90,8 @@
group-chat (get-in cofx [:db :chats chat-id :group-chat])] group-chat (get-in cofx [:db :chats chat-id :group-chat])]
(if (or group-chat (if (or group-chat
config/use-sym-key) config/use-sym-key)
(send params cofx) (send cofx params)
(send-with-pubkey params cofx)))) (send-with-pubkey cofx params))))
(receive [this chat-id signature _ cofx] (receive [this chat-id signature _ cofx]
{:chat-received-message/add-fx {:chat-received-message/add-fx
[(assoc (into {} this) [(assoc (into {} this)
@ -109,8 +104,8 @@
(defrecord MessagesSeen [message-ids] (defrecord MessagesSeen [message-ids]
message/StatusMessage message/StatusMessage
(send [this chat-id cofx] (send [this chat-id cofx]
(send {:chat-id chat-id (send cofx
:payload this} {:chat-id chat-id
cofx)) :payload this}))
(receive [this chat-id signature _ cofx] (receive [this chat-id signature _ cofx]
(chat/receive-seen chat-id signature this cofx))) (chat/receive-seen cofx chat-id signature this)))

View File

@ -1,29 +1,28 @@
(ns ^{:doc "Public chat API"} (ns ^{:doc "Public chat API"}
status-im.transport.message.v1.public-chat status-im.transport.message.v1.public-chat
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers] [status-im.data-store.transport :as transport-store]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.transport.message.core :as message]
[status-im.transport.message.v1.protocol :as protocol] [status-im.transport.message.v1.protocol :as protocol]
[status-im.transport.utils :as transport.utils] [status-im.transport.utils :as transport.utils]
[status-im.data-store.transport :as transport-store])) [status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]))
(defn- has-already-joined? [chat-id {:keys [db]}] (defn- has-already-joined? [{:keys [db]} chat-id]
(get-in db [:transport/chats chat-id])) (get-in db [:transport/chats chat-id]))
(defn join-public-chat (fx/defn join-public-chat
"Function producing all protocol level effects necessary for joining public chat identified by chat-id" "Function producing all protocol level effects necessary for joining public chat identified by chat-id"
[chat-id {:keys [db] :as cofx}] [{:keys [db] :as cofx} chat-id]
(when-not (has-already-joined? chat-id cofx) (when-not (has-already-joined? cofx chat-id)
(let [on-success (fn [sym-key sym-key-id] (let [on-success (fn [sym-key sym-key-id]
(re-frame/dispatch [::add-new-sym-key {:chat-id chat-id (re-frame/dispatch [::add-new-sym-key {:chat-id chat-id
:sym-key sym-key :sym-key sym-key
:sym-key-id sym-key-id}]))] :sym-key-id sym-key-id}]))]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:shh/generate-sym-key-from-password [{:web3 (:web3 db) {:shh/generate-sym-key-from-password [{:web3 (:web3 db)
:password chat-id :password chat-id
:on-success on-success}]} :on-success on-success}]}
(protocol/init-chat {:chat-id chat-id}))))) (protocol/init-chat {:chat-id chat-id})))))
(handlers/register-handler-fx (handlers/register-handler-fx
::add-new-sym-key ::add-new-sym-key

View File

@ -4,11 +4,12 @@
[cljs-time.core :refer [now]] [cljs-time.core :refer [now]]
[clojure.string :as string] [clojure.string :as string]
[status-im.js-dependencies :as dependencies] [status-im.js-dependencies :as dependencies]
[status-im.data-store.transport :as transport-store])) [status-im.data-store.transport :as transport-store]
[status-im.utils.fx :as fx]))
(defn unsubscribe-from-chat (fx/defn unsubscribe-from-chat
"Unsubscribe from chat on transport layer" "Unsubscribe from chat on transport layer"
[chat-id {:keys [db]}] [{:keys [db]} chat-id]
(let [filter (get-in db [:transport/chats chat-id :filter])] (let [filter (get-in db [:transport/chats chat-id :filter])]
{:db (update db :transport/chats dissoc chat-id) {:db (update db :transport/chats dissoc chat-id)
:data-store/tx [(transport-store/delete-transport-tx chat-id)] :data-store/tx [(transport-store/delete-transport-tx chat-id)]

View File

@ -1,6 +1,5 @@
(ns status-im.ui.components.desktop.events (ns status-im.ui.components.desktop.events
(:require [status-im.utils.handlers :as handlers] (:require [status-im.utils.handlers :as handlers]))
[status-im.utils.handlers-macro :as handlers-macro]))
(handlers/register-handler-fx (handlers/register-handler-fx
:show-desktop-tab :show-desktop-tab

View File

@ -7,4 +7,4 @@
:handle-qr-code :handle-qr-code
(fn [cofx [_ _ data]] (fn [cofx [_ _ data]]
(log/debug "qr code scanned with data " data) (log/debug "qr code scanned with data " data)
(models/handle-qr-code data cofx))) (models/handle-qr-code cofx data)))

View File

@ -4,17 +4,19 @@
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.universal-links.core :as universal-links] [status-im.utils.universal-links.core :as universal-links]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn- process-qr-code [data cofx] (fx/defn process-qr-code
[cofx data]
(if (spec/valid? :global/public-key data) (if (spec/valid? :global/public-key data)
(universal-links/handle-view-profile data cofx) (universal-links/handle-view-profile cofx data)
(or (universal-links/handle-url data cofx) (or (universal-links/handle-url cofx data)
{:utils/show-popup [(i18n/label :t/unable-to-read-this-code) {:utils/show-popup [(i18n/label :t/unable-to-read-this-code)
(i18n/label :t/use-valid-qr-code {:data data}) (i18n/label :t/use-valid-qr-code {:data data})
#(re-frame/dispatch [:navigate-to-clean :home])]}))) #(re-frame/dispatch [:navigate-to-clean :home])]})))
(defn handle-qr-code [data cofx] (fx/defn handle-qr-code
(handlers-macro/merge-fx cofx [cofx data]
(navigation/navigate-to-clean :home) (fx/merge cofx
(process-qr-code data))) (navigation/navigate-to-clean :home {})
(process-qr-code data)))

View File

@ -1,11 +1,10 @@
(ns status-im.ui.screens.add-new.new-chat.events (ns status-im.ui.screens.add-new.new-chat.events
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.add-new.new-chat.db :as db] [status-im.ui.screens.add-new.new-chat.db :as db]
[status-im.utils.ethereum.stateofus :as stateofus] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.ens :as ens] [status-im.utils.ethereum.ens :as ens]
[status-im.utils.ethereum.core :as ethereum])) [status-im.utils.ethereum.stateofus :as stateofus]
[status-im.utils.handlers :as handlers]))
(re-frame/reg-fx (re-frame/reg-fx
:resolve-whisper-identity :resolve-whisper-identity

View File

@ -7,15 +7,15 @@
[status-im.ui.screens.browser.default-dapps :as default-dapps] [status-im.ui.screens.browser.default-dapps :as default-dapps]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.js-resources :as js-res] [status-im.utils.js-resources :as js-res]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]))
(defn add-contact-and-open-chat [whisper-id cofx] (fx/defn add-contact-and-open-chat
(handlers-macro/merge-fx [cofx whisper-id]
cofx (fx/merge cofx
(models.contact/add-contact whisper-id) (models.contact/add-contact whisper-id)
(chat.models/start-chat whisper-id {:navigation-replace? true}))) (chat.models/start-chat whisper-id {:navigation-replace? true})))
(re-frame/reg-cofx (re-frame/reg-cofx
:get-default-contacts :get-default-contacts
@ -31,7 +31,7 @@
:add-contact :add-contact
[(re-frame/inject-cofx :random-id)] [(re-frame/inject-cofx :random-id)]
(fn [cofx [_ whisper-id]] (fn [cofx [_ whisper-id]]
(models.contact/add-contact whisper-id cofx))) (models.contact/add-contact cofx whisper-id)))
(handlers/register-handler-fx (handlers/register-handler-fx
:hide-contact :hide-contact
@ -48,28 +48,28 @@
validation-result (new-chat.db/validate-pub-key db contact-identity)] validation-result (new-chat.db/validate-pub-key db contact-identity)]
(if (some? validation-result) (if (some? validation-result)
(utils/show-popup (i18n/label :t/unable-to-read-this-code) validation-result #(re-frame/dispatch [:navigate-to-clean :home])) (utils/show-popup (i18n/label :t/unable-to-read-this-code) validation-result #(re-frame/dispatch [:navigate-to-clean :home]))
(handlers-macro/merge-fx cofx (fx/merge cofx
fx fx
(add-contact-and-open-chat contact-identity)))))) (add-contact-and-open-chat contact-identity))))))
(handlers/register-handler-fx (handlers/register-handler-fx
:open-contact-toggle-list :open-contact-toggle-list
(fn [{:keys [db] :as cofx} _] (fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db {:db (assoc db
:group/selected-contacts #{} :group/selected-contacts #{}
:new-chat-name "")} :new-chat-name "")}
(navigation/navigate-to-cofx :contact-toggle-list nil)))) (navigation/navigate-to-cofx :contact-toggle-list nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:open-chat-with-contact :open-chat-with-contact
[(re-frame/inject-cofx :random-id)] [(re-frame/inject-cofx :random-id)]
(fn [cofx [_ {:keys [whisper-identity]}]] (fn [cofx [_ {:keys [whisper-identity]}]]
(add-contact-and-open-chat whisper-identity cofx))) (add-contact-and-open-chat cofx whisper-identity)))
(handlers/register-handler-fx (handlers/register-handler-fx
:add-contact-handler :add-contact-handler
[(re-frame/inject-cofx :random-id)] [(re-frame/inject-cofx :random-id)]
(fn [{{:contacts/keys [new-identity]} :db :as cofx} _] (fn [{{:contacts/keys [new-identity]} :db :as cofx} _]
(when (seq new-identity) (when (seq new-identity)
(add-contact-and-open-chat new-identity cofx)))) (add-contact-and-open-chat cofx new-identity))))

View File

@ -1,11 +1,12 @@
(ns status-im.ui.screens.currency-settings.models (ns status-im.ui.screens.currency-settings.models
(:require [status-im.accounts.update.core :as accounts.update] (:require [status-im.accounts.update.core :as accounts.update]
[status-im.models.wallet :as wallet] [status-im.models.wallet :as wallet]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn set-currency [currency {:keys [db] :as cofx}] (fx/defn set-currency
[{:keys [db] :as cofx} currency]
(let [settings (get-in db [:account/account :settings]) (let [settings (get-in db [:account/account :settings])
new-settings (assoc-in settings [:wallet :currency] currency)] new-settings (assoc-in settings [:wallet :currency] currency)]
(handlers-macro/merge-fx cofx (fx/merge cofx
(accounts.update/update-settings new-settings) (accounts.update/update-settings new-settings {})
(wallet/update-wallet)))) (wallet/update-wallet))))

View File

@ -2,13 +2,12 @@
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(defn show-profile-desktop [identity {:keys [db] :as cofx}] (defn show-profile-desktop [identity {:keys [db] :as cofx}]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (assoc db :contacts/identity identity)}
{:db (assoc db :contacts/identity identity)} (navigation/navigate-to-cofx :chat-profile nil)))
(navigation/navigate-to-cofx :chat-profile nil)))
(handlers/register-handler-fx (handlers/register-handler-fx
:show-profile-desktop :show-profile-desktop

View File

@ -30,9 +30,9 @@
[status-im.ui.components.permissions :as permissions] [status-im.ui.components.permissions :as permissions]
[status-im.utils.dimensions :as dimensions] [status-im.utils.dimensions :as dimensions]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.http :as http] [status-im.utils.http :as http]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]))
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}] (defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
(let [on-success #(re-frame/dispatch (success-event-creator %)) (let [on-success #(re-frame/dispatch (success-event-creator %))
@ -103,13 +103,18 @@
(fn [{:keys [db]} [_ path v]] (fn [{:keys [db]} [_ path v]]
{:db (assoc-in db path v)})) {:db (assoc-in db path v)}))
(fx/defn on-return-from-background [cofx]
(fx/merge cofx
(inbox/request-messages)
(hardwallet/return-back-from-nfc-settings)))
(defn app-state-change [state {:keys [db] :as cofx}] (defn app-state-change [state {:keys [db] :as cofx}]
(let [app-coming-from-background? (= state "active")] (let [app-coming-from-background? (= state "active")]
(handlers-macro/merge-fx cofx (fx/merge cofx
{::app-state-change-fx state {::app-state-change-fx state
:db (assoc db :app-state state)} :db (assoc db :app-state state)}
(inbox/request-messages app-coming-from-background?) #(when app-coming-from-background?
(hardwallet/return-back-from-nfc-settings app-coming-from-background?)))) (on-return-from-background %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:app-state-change :app-state-change

View File

@ -5,7 +5,7 @@
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.fx :as fx]))
(re-frame/reg-fx (re-frame/reg-fx
:extension/load :extension/load
@ -16,13 +16,13 @@
:extension/install :extension/install
(fn [cofx [_ extension-data]] (fn [cofx [_ extension-data]]
(let [extension-key (get-in extension-data ['meta :name])] (let [extension-key (get-in extension-data ['meta :name])]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:ui/show-confirmation {:title (i18n/label :t/success) {:ui/show-confirmation {:title (i18n/label :t/success)
:content (i18n/label :t/extension-installed) :content (i18n/label :t/extension-installed)
:on-accept #(re-frame/dispatch [:navigate-to-clean :home]) :on-accept #(re-frame/dispatch [:navigate-to-clean :home])
:on-cancel nil}} :on-cancel nil}}
(registry/add extension-data) #(registry/add extension-data %)
(registry/activate extension-key))))) #(registry/activate extension-key %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:extension/edit-address :extension/edit-address
@ -32,9 +32,9 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:extension/stage :extension/stage
(fn [{:keys [db] :as cofx} [_ extension-data]] (fn [{:keys [db] :as cofx} [_ extension-data]]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db :staged-extension extension-data)} {:db (assoc db :staged-extension extension-data)}
(navigation/navigate-to-cofx :show-extension nil)))) (navigation/navigate-to-cofx :show-extension nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:extension/show :extension/show

View File

@ -6,17 +6,17 @@
[status-im.transport.message.v1.group-chat :as group-chat] [status-im.transport.message.v1.group-chat :as group-chat]
[status-im.transport.message.core :as transport] [status-im.transport.message.core :as transport]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.data-store.chats :as chats-store]
[status-im.data-store.chats :as chats-store])) [status-im.utils.fx :as fx]))
(handlers/register-handler-fx (handlers/register-handler-fx
:show-group-chat-profile :show-group-chat-profile
(fn [{:keys [db] :as cofx} [_ chat-id]] (fn [{:keys [db] :as cofx} [_ chat-id]]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc db {:db (assoc db
:new-chat-name (get-in db [:chats chat-id :name]) :new-chat-name (get-in db [:chats chat-id :name])
:group/group-type :chat-group)} :group/group-type :chat-group)}
(navigation/navigate-to-cofx :group-chat-profile nil)))) (navigation/navigate-to-cofx :group-chat-profile nil))))
(handlers/register-handler-fx (handlers/register-handler-fx
:add-new-group-chat-participants :add-new-group-chat-participants
@ -25,15 +25,15 @@
(let [participants (concat (get-in db [:chats current-chat-id :contacts]) selected-participants) (let [participants (concat (get-in db [:chats current-chat-id :contacts]) selected-participants)
contacts (:contacts/contacts db) contacts (:contacts/contacts db)
added-participants-names (map #(get-in contacts [% :name]) selected-participants)] added-participants-names (map #(get-in contacts [% :name]) selected-participants)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:chats current-chat-id :contacts] participants) (assoc-in [:chats current-chat-id :contacts] participants)
(assoc :selected-participants #{})) (assoc :selected-participants #{}))
:data-store/tx [(chats-store/add-chat-contacts-tx current-chat-id selected-participants)]} :data-store/tx [(chats-store/add-chat-contacts-tx current-chat-id selected-participants)]}
(models.message/receive (models.message/receive
(models.message/system-message current-chat-id message-id now (models.message/system-message current-chat-id message-id now
(str "You've added " (apply str (interpose ", " added-participants-names))))) (str "You've added " (apply str (interpose ", " added-participants-names)))))
(transport/send (group-chat/GroupAdminUpdate. nil participants) current-chat-id))))) #(transport/send (group-chat/GroupAdminUpdate. nil participants) current-chat-id %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:remove-group-chat-participants :remove-group-chat-participants
@ -42,13 +42,13 @@
(let [participants (remove removed-participants (get-in db [:chats current-chat-id :contacts])) (let [participants (remove removed-participants (get-in db [:chats current-chat-id :contacts]))
contacts (:contacts/contacts db) contacts (:contacts/contacts db)
removed-participants-names (map #(get-in contacts [% :name]) removed-participants)] removed-participants-names (map #(get-in contacts [% :name]) removed-participants)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (assoc-in db [:chats current-chat-id :contacts] participants) {:db (assoc-in db [:chats current-chat-id :contacts] participants)
:data-store/tx [(chats-store/remove-chat-contacts-tx current-chat-id removed-participants)]} :data-store/tx [(chats-store/remove-chat-contacts-tx current-chat-id removed-participants)]}
(models.message/receive (models.message/receive
(models.message/system-message current-chat-id message-id now (models.message/system-message current-chat-id message-id now
(str "You've removed " (apply str (interpose ", " removed-participants-names))))) (str "You've removed " (apply str (interpose ", " removed-participants-names)))))
(transport/send (group-chat/GroupAdminUpdate. nil participants) current-chat-id))))) #(transport/send (group-chat/GroupAdminUpdate. nil participants) current-chat-id %)))))
(handlers/register-handler-fx (handlers/register-handler-fx
:set-group-chat-name :set-group-chat-name

View File

@ -1,14 +1,17 @@
(ns status-im.ui.screens.group.core (ns status-im.ui.screens.group.core
(:require [status-im.data-store.chats :as chats-store])) (:require [status-im.data-store.chats :as chats-store]
[status-im.utils.fx :as fx]))
(defn participants-added [chat-id added-participants-set {:keys [db] :as cofx}] (fx/defn participants-added
[{:keys [db] :as cofx} chat-id added-participants-set]
(when (seq added-participants-set) (when (seq added-participants-set)
{:db (update-in db [:chats chat-id :contacts] {:db (update-in db [:chats chat-id :contacts]
concat added-participants-set) concat added-participants-set)
:data-store/tx [(chats-store/add-chat-contacts-tx :data-store/tx [(chats-store/add-chat-contacts-tx
chat-id added-participants-set)]})) chat-id added-participants-set)]}))
(defn participants-removed [chat-id removed-participants-set {:keys [now db] :as cofx}] (fx/defn participants-removed
[{:keys [now db] :as cofx} chat-id removed-participants-set]
(when (seq removed-participants-set) (when (seq removed-participants-set)
(let [{:keys [is-active timestamp]} (get-in db [:chats chat-id])] (let [{:keys [is-active timestamp]} (get-in db [:chats chat-id])]
;;TODO: not sure what this condition is for ;;TODO: not sure what this condition is for

View File

@ -1,9 +1,9 @@
(ns status-im.ui.screens.navigation (ns status-im.ui.screens.navigation
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.navigation :as navigation] [status-im.utils.navigation :as navigation]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
;; private helper fns ;; private helper fns
@ -20,20 +20,22 @@
;; public fns ;; public fns
(defn navigate-to-clean (fx/defn navigate-to-clean
([view-id cofx] (navigate-to-clean view-id cofx nil)) [{:keys [db]} view-id screen-params]
([view-id {:keys [db]} screen-params] (log/debug "current view-id " (:view-id db)
(log/debug "current view-id " (:view-id db)) "changing to " view-id)
(let [db (cond-> db (let [db (cond-> db
(seq screen-params) (seq screen-params)
(assoc-in [:navigation/screen-params view-id] screen-params))] (assoc-in [:navigation/screen-params view-id] screen-params))]
{:db (push-view db view-id) {:db (push-view db view-id)
::navigate-to-clean view-id}))) ::navigate-to-clean view-id}))
(defn replace-view [view-id _] (fx/defn replace-view
[_ view-id]
{::navigate-replace view-id}) {::navigate-replace view-id})
(defn navigate-forget [view-id {:keys [db]}] (fx/defn navigate-forget
[{:keys [db]} view-id]
{:db (assoc db :view-id view-id)}) {:db (assoc db :view-id view-id)})
(defmulti unload-data! (defmulti unload-data!
@ -51,7 +53,8 @@
(dissoc db :was-modal?) ;;TODO check how it worked with this bug (dissoc db :was-modal?) ;;TODO check how it worked with this bug
(apply preload-data! db args))) (apply preload-data! db args)))
(defn navigate-to-cofx [go-to-view-id screen-params {:keys [db]}] (fx/defn navigate-to-cofx
[{:keys [db]} go-to-view-id screen-params]
(let [view-id (:view-id db) (let [view-id (:view-id db)
db (cond-> (assoc db :view-id go-to-view-id) db (cond-> (assoc db :view-id go-to-view-id)
(seq screen-params) (seq screen-params)
@ -62,8 +65,8 @@
(push-view db go-to-view-id)) (push-view db go-to-view-id))
::navigate-to go-to-view-id})) ::navigate-to go-to-view-id}))
(defn navigate-reset (fx/defn navigate-reset
[{:keys [index actions] :as config} {:keys [db]}] [{:keys [db]} {:keys [index actions] :as config}]
{:db (assoc db :view-id {:db (assoc db :view-id
(:routeName (get actions index))) (:routeName (get actions index)))
::navigate-reset config}) ::navigate-reset config})
@ -119,7 +122,7 @@
:navigate-to :navigate-to
navigation-interceptors navigation-interceptors
(fn [cofx [_ & [go-to-view-id screen-params]]] (fn [cofx [_ & [go-to-view-id screen-params]]]
(navigate-to-cofx go-to-view-id screen-params cofx))) (navigate-to-cofx cofx go-to-view-id screen-params)))
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-to-modal :navigate-to-modal
@ -133,7 +136,7 @@
(fn [cofx [_ view-id]] (fn [cofx [_ view-id]]
(replace-view view-id cofx))) (replace-view view-id cofx)))
(defn navigate-back (fx/defn navigate-back
[{{:keys [navigation-stack view-id] :as db} :db}] [{{:keys [navigation-stack view-id] :as db} :db}]
(assoc (assoc
{::navigate-back nil} {::navigate-back nil}
@ -154,14 +157,14 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-to-clean :navigate-to-clean
(fn [cofx [_ view-id params]] (fn [cofx [_ view-id params]]
(navigate-to-clean view-id cofx params))) (navigate-to-clean cofx view-id params)))
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-to-tab :navigate-to-tab
navigation-interceptors navigation-interceptors
(fn [{:keys [db] :as cofx} [_ view-id]] (fn [{:keys [db] :as cofx} [_ view-id]]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc :prev-tab-view-id (:view-id db)) (assoc :prev-tab-view-id (:view-id db))
(assoc :prev-view-id (:view-id db)))} (assoc :prev-view-id (:view-id db)))}
(navigate-to-cofx view-id {})))) (navigate-to-cofx view-id {}))))

View File

@ -6,9 +6,9 @@
[status-im.accounts.update.core :as accounts.update] [status-im.accounts.update.core :as accounts.update]
[status-im.chat.models :as chat-models] [status-im.chat.models :as chat-models]
[status-im.chat.commands.input :as commands-input] [status-im.chat.commands.input :as commands-input]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.image-processing :as image-processing] [status-im.utils.image-processing :as image-processing]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn open-image-picker! [callback-event] (defn open-image-picker! [callback-event]
(react/show-image-picker (react/show-image-picker
@ -23,9 +23,9 @@
(defn send-transaction [chat-id {:keys [db] :as cofx}] (defn send-transaction [chat-id {:keys [db] :as cofx}]
(let [send-command (get-in db [:id->command ["send" #{:personal-chats}]])] (let [send-command (get-in db [:id->command ["send" #{:personal-chats}]])]
(handlers-macro/merge-fx cofx (fx/merge cofx
(chat-models/start-chat chat-id {:navigation-replace? true}) (chat-models/start-chat chat-id {:navigation-replace? true})
(commands-input/select-chat-input-command send-command nil)))) (commands-input/select-chat-input-command send-command nil))))
(defn- valid-name? [name] (defn- valid-name? [name]
(spec/valid? :profile/name name)) (spec/valid? :profile/name name))
@ -49,7 +49,8 @@
name name
(get-in db [:account/account :name])))) (get-in db [:account/account :name]))))
(defn clear-profile [{:keys [db]}] (fx/defn clear-profile
[{:keys [db]}]
{:db (dissoc db :my-profile/profile :my-profile/default-name :my-profile/editing?)}) {:db (dissoc db :my-profile/profile :my-profile/default-name :my-profile/editing?)})
(defn start-editing [{:keys [db]}] (defn start-editing [{:keys [db]}]
@ -65,9 +66,9 @@
:last-updated now} :last-updated now}
(if photo-path (if photo-path
{:photo-path photo-path}))] {:photo-path photo-path}))]
(handlers-macro/merge-fx cofx (fx/merge cofx
(clear-profile) (clear-profile)
(accounts.update/account-update cleaned-edit)))) (accounts.update/account-update cleaned-edit {}))))
(defn start-editing-group-chat-profile [{:keys [db]}] (defn start-editing-group-chat-profile [{:keys [db]}]
{:db (assoc db :group-chat-profile/editing? true)}) {:db (assoc db :group-chat-profile/editing? true)})
@ -87,9 +88,9 @@
{:db (update db :my-profile/seed assoc :step step :error nil :word nil)}) {:db (update db :my-profile/seed assoc :step step :error nil :word nil)})
(defn finish [{:keys [db] :as cofx}] (defn finish [{:keys [db] :as cofx}]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (update db :my-profile/seed assoc :step :finish :error nil :word nil)} {:db (update db :my-profile/seed assoc :step :finish :error nil :word nil)}
(accounts.update/clean-seed-phrase))) (accounts.update/clean-seed-phrase)))
(defn copy-to-clipboard! [value] (defn copy-to-clipboard! [value]
(react/copy-to-clipboard value)) (react/copy-to-clipboard value))

View File

@ -66,4 +66,4 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:open-collectible-in-browser :open-collectible-in-browser
(fn [cofx [_ url]] (fn [cofx [_ url]]
(browser/open-url url cofx))) (browser/open-url cofx url)))

View File

@ -9,10 +9,10 @@
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.prices :as prices] [status-im.utils.prices :as prices]
[status-im.utils.transactions :as transactions] [status-im.utils.transactions :as transactions]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn get-balance [{:keys [web3 account-id on-success on-error]}] (defn get-balance [{:keys [web3 account-id on-success on-error]}]
(if (and web3 account-id) (if (and web3 account-id)
@ -168,7 +168,7 @@
(assoc-error-message :balance-update :error-unable-to-get-balance) (assoc-error-message :balance-update :error-unable-to-get-balance)
(assoc-in [:wallet :balance-loading?] false))})) (assoc-in [:wallet :balance-loading?] false))}))
(defn update-token-balance-success [symbol balance {:keys [db]}] (fx/defn update-token-balance-success [{:keys [db]} symbol balance]
{:db (-> db {:db (-> db
(assoc-in [:wallet :balance symbol] balance) (assoc-in [:wallet :balance symbol] balance)
(assoc-in [:wallet :balance-loading?] false))}) (assoc-in [:wallet :balance-loading?] false))})
@ -176,7 +176,7 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:update-token-balance-success :update-token-balance-success
(fn [cofx [_ symbol balance]] (fn [cofx [_ symbol balance]]
(update-token-balance-success symbol balance cofx))) (update-token-balance-success cofx symbol balance)))
(handlers/register-handler-fx (handlers/register-handler-fx
:update-token-balance-fail :update-token-balance-fail
@ -242,7 +242,6 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet-setup-navigate-back :wallet-setup-navigate-back
(fn [{:keys [db] :as cofx}] (fn [{:keys [db] :as cofx}]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:db (assoc-in db [:wallet :send-transaction] {})}
{:db (assoc-in db [:wallet :send-transaction] {})} (navigation/navigate-back))))
(navigation/navigate-back))))

View File

@ -5,20 +5,20 @@
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.chat.commands.sending :as commands-sending] [status-im.chat.commands.sending :as commands-sending]
[status-im.utils.money :as money] [status-im.utils.fx :as fx]
[status-im.utils.handlers-macro :as handlers-macro])) [status-im.utils.money :as money]))
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet-send-request :wallet-send-request
(fn [{:keys [db] :as cofx} [_ whisper-identity amount symbol decimals]] (fn [{:keys [db] :as cofx} [_ whisper-identity amount symbol decimals]]
(assert whisper-identity) (assert whisper-identity)
(let [request-command (get-in db [:id->command ["request" #{:personal-chats}]])] (let [request-command (get-in db [:id->command ["request" #{:personal-chats}]])]
(handlers-macro/merge-fx cofx (fx/merge cofx
(chat-model/start-chat whisper-identity nil) (chat-model/start-chat whisper-identity nil)
(commands-sending/send whisper-identity (commands-sending/send whisper-identity
request-command request-command
{:asset (name symbol) {:asset (name symbol)
:amount (str (money/internal->formatted amount symbol decimals))}))))) :amount (str (money/internal->formatted amount symbol decimals))})))))
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet.request/set-and-validate-amount :wallet.request/set-and-validate-amount

View File

@ -1,5 +1,4 @@
(ns status-im.ui.screens.wallet.send.events (ns status-im.ui.screens.wallet.send.events
(:require-macros [status-im.utils.handlers-macro :as handlers-macro])
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.chat.commands.sending :as commands-sending] [status-im.chat.commands.sending :as commands-sending]
[status-im.chat.models.message :as models.message] [status-im.chat.models.message :as models.message]
@ -13,8 +12,8 @@
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.erc20 :as erc20] [status-im.utils.ethereum.erc20 :as erc20]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types] [status-im.utils.types :as types]
@ -150,8 +149,7 @@
:data data :data data
:dapp-transaction queued-transaction :dapp-transaction queued-transaction
:method method})] :method method})]
(navigation/navigate-to-cofx (navigation/navigate-to-cofx {:db db''} :wallet-sign-message-modal nil))
:wallet-sign-message-modal nil {:db db''}))
{:db db'}))))))) {:db db'})))))))
(handlers/register-handler-fx (handlers/register-handler-fx
@ -161,12 +159,11 @@
(fn [{:keys [db] :as cofx} [_ chat-id params]] (fn [{:keys [db] :as cofx} [_ chat-id params]]
;;NOTE(goranjovic): we want to send the payment message only when we have a whisper id ;;NOTE(goranjovic): we want to send the payment message only when we have a whisper id
;; for the recipient, we always redirect to `:wallet-transaction-sent` even when we don't ;; for the recipient, we always redirect to `:wallet-transaction-sent` even when we don't
(if-let [send-command (and chat-id (get-in db [:id->command ["send" #{:personal-chats}]]))] (let [send-command? (and chat-id (get-in db [:id->command ["send" #{:personal-chats}]]))]
(handlers-macro/merge-fx cofx (fx/merge cofx
(commands-sending/send chat-id send-command params) #(when send-command?
(navigation/navigate-to-clean :wallet-transaction-sent)) (commands-sending/send % chat-id send-command? params))
(handlers-macro/merge-fx cofx (navigation/navigate-to-clean :wallet-transaction-sent {})))))
(navigation/navigate-to-clean :wallet-transaction-sent)))))
(defn set-and-validate-amount-db [db amount symbol decimals] (defn set-and-validate-amount-db [db amount symbol decimals]
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)] (let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
@ -266,10 +263,9 @@
(handlers/register-handler-fx (handlers/register-handler-fx
:close-transaction-sent-screen :close-transaction-sent-screen
(fn [{:keys [db] :as cofx} [_ chat-id]] (fn [{:keys [db] :as cofx} [_ chat-id]]
(handlers-macro/merge-fx (fx/merge cofx
cofx {:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]}
{:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]} (navigation/navigate-back))))
(navigation/navigate-back))))
(handlers/register-handler-fx (handlers/register-handler-fx
:sync-wallet-transactions :sync-wallet-transactions

View File

@ -1,17 +1,17 @@
(ns status-im.ui.screens.wallet.settings.events (ns status-im.ui.screens.wallet.settings.events
(:require [status-im.ui.screens.wallet.settings.models :as models] (:require [status-im.ui.screens.wallet.settings.models :as models]
[status-im.accounts.update.core :as accounts.update]
[status-im.utils.handlers :as handlers])) [status-im.utils.handlers :as handlers]))
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet.settings/toggle-visible-token :wallet.settings/toggle-visible-token
(fn [cofx [_ symbol checked?]] (fn [cofx [_ symbol checked?]]
(models/toggle-visible-token symbol checked? accounts.update/update-settings cofx))) (models/toggle-visible-token cofx symbol checked?)))
(handlers/register-handler-fx (handlers/register-handler-fx
:configure-token-balance-and-visibility :configure-token-balance-and-visibility
(fn [cofx [_ symbol balance]] (fn [cofx [_ symbol balance]]
(models/configure-token-balance-and-visibility symbol balance accounts.update/update-settings cofx))) (models/configure-token-balance-and-visibility cofx symbol balance)))
(handlers/register-handler-fx (handlers/register-handler-fx
:wallet.ui/pull-to-refresh :wallet.ui/pull-to-refresh

View File

@ -1,29 +1,30 @@
(ns status-im.ui.screens.wallet.settings.models (ns status-im.ui.screens.wallet.settings.models
(:require [status-im.utils.ethereum.core :as ethereum] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.accounts.update.core :as accounts.update]
[status-im.ui.screens.wallet.events :as wallet.events] [status-im.ui.screens.wallet.events :as wallet.events]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[re-frame.core :as re-frame])) [status-im.utils.fx :as fx]))
(defn- set-checked [ids id checked?] (defn- set-checked [ids id checked?]
(if checked? (if checked?
(conj (or ids #{}) id) (conj (or ids #{}) id)
(disj ids id))) (disj ids id)))
(defn toggle-visible-token [symbol checked? update-settings-fx {{:keys [account/account]} :db :as cofx}] (fx/defn toggle-visible-token [{{:account/keys [account]} :db :as cofx} symbol checked?]
(let [network (get (:networks account) (:network account)) (let [network (get (:networks account) (:network account))
chain (ethereum/network->chain-keyword network) chain (ethereum/network->chain-keyword network)
settings (get account :settings) settings (get account :settings)
new-settings (update-in settings [:wallet :visible-tokens chain] #(set-checked % symbol checked?))] new-settings (update-in settings [:wallet :visible-tokens chain] #(set-checked % symbol checked?))]
(update-settings-fx new-settings cofx))) (accounts.update/update-settings cofx new-settings {})))
(defn configure-token-balance-and-visibility [symbol balance update-settings-fx cofx] (fx/defn configure-token-balance-and-visibility [cofx symbol balance]
(handlers-macro/merge-fx cofx (fx/merge cofx
(toggle-visible-token symbol true update-settings-fx) (toggle-visible-token symbol true)
;;TODO(goranjovic): move `update-token-balance-success` function to wallet models ;;TODO(goranjovic): move `update-token-balance-success` function to wallet models
(wallet.events/update-token-balance-success symbol balance))) (wallet.events/update-token-balance-success symbol balance)))
(defn wallet-autoconfig-tokens [{:keys [db]}] (fx/defn wallet-autoconfig-tokens [{:keys [db]}]
(let [{:keys [account/account web3 network-status]} db (let [{:keys [account/account web3 network-status]} db
network (get (:networks account) (:network account)) network (get (:networks account) (:network account))
chain (ethereum/network->chain-keyword network) chain (ethereum/network->chain-keyword network)

View File

@ -1,7 +1,7 @@
(ns status-im.utils.fx (ns status-im.utils.fx
(:require-macros status-im.utils.fx (:require-macros status-im.utils.fx)
[taoensso.timbre :as log]) (:require [clojure.set :as set]
(:require [clojure.set :as set]) [taoensso.timbre :as log])
(:refer-clojure :exclude [merge])) (:refer-clojure :exclude [merge]))
(defn- update-db [cofx fx] (defn- update-db [cofx fx]

View File

@ -1,56 +0,0 @@
(ns status-im.utils.handlers-macro)
(defmacro merge-fx*
"This macro is called recursively from merge-fx
It wraps each form in a let binding that captures
- the new co-effect after updating the db key if a db effect was in the map returned
by the previous form
- the new fx map after merging previous fx map with the map returned by the previous form
We use safe-merge for that which is returning a map with a :merging-fx-with-common-keys effect
in case at least one effect that is not a :db effect was overwritten by merge"
{:added "1.0"}
[fx cofx & forms]
(if forms
(let [form (first forms)
temp-cofx (gensym 'temp-cofx)]
`(let [~temp-cofx (update-db ~cofx ~fx)
fx# (safe-merge ~fx ~(with-meta `(~(first form) ~@(next form) ~temp-cofx) (meta form)))]
(merge-fx* fx# ~temp-cofx ~@(next forms))))
fx))
(defmacro merge-fx
"Takes a map of co-effects and forms as argument.
The first optional form can be map of effects/
The next forms are functions applying effects and returning a map of effects.
The macro ensures that updates to db are passed from function to function within the cofx :db key and
that only a :merging-fx-with-common-keys effect is returned if some functions are trying
to produce the same effects (excepted :db, :data-source/tx and :data-source/base-tx effects).
:data-source/tx and :data-source/base-tx effects are handled specially and their results
(list of transactions) are compacted to one transactions list (for each effect). "
{:added "1.0"
:deprecated "Please use utils.fx/merge function instead"}
[cofx & forms]
(let [form (first forms)]
(if (or (symbol? form)
(map? form))
`(merge-fx* ~form ~cofx ~@(next forms))
`(merge-fx* {} ~cofx ~@forms))))
(comment (defn fn1 [{:keys [db]}]
{:db (assoc db :a 0)
:a "1"})
(defn fn2 [a {:keys [db]}]
{:db (update db :a + a)})
(defn fn3 [a {:keys [db u]}]
{:db (update db :a + u)})
(let [a 1
b 2
cofx {:db {} :u 1}]
(merge-fx cofx
{:db {:hello 2}}
(fn1)
(fn2 a)
(fn3 b))))

View File

@ -1,7 +1,6 @@
(ns status-im.utils.handlers-macro (ns status-im.utils.handlers-macro
(:require-macros status-im.utils.handlers-macro (:require [clojure.set :as set]
[taoensso.timbre :as log]) [taoensso.timbre :as log]))
(:require [clojure.set :as set]))
(defn update-db [cofx fx] (defn update-db [cofx fx]
(if-let [db (:db fx)] (if-let [db (:db fx)]

View File

@ -1,13 +1,15 @@
(ns status-im.utils.semaphores) (ns status-im.utils.semaphores
(:require [status-im.utils.fx :as fx]))
(defn lock [semaphore {:keys [db]}] (fx/defn lock [{:keys [db]} semaphore]
{:pre [(keyword? semaphore)]} #_{:pre [(keyword? semaphore)]}
{:db (update db :semaphores conj semaphore)}) {:db (update db :semaphores conj semaphore)})
(defn free [semaphore {:keys [db]}] (fx/defn free [{:keys [db]} semaphore]
{:pre [(keyword? semaphore)]} #_{:pre [(keyword? semaphore)]}
(update db :semaphores disj semaphore)) (println {:db (update db :semaphores disj semaphore)})
{:db (update db :semaphores disj semaphore)})
(defn locked? [semaphore cofx] (defn locked? [{:keys [db]} semaphore]
{:pre [(keyword? semaphore)]} #_{:pre [(keyword? semaphore)]}
((get-in cofx [:db :semaphores]) semaphore)) ((get db :semaphores) semaphore))

View File

@ -1,16 +1,15 @@
(ns status-im.utils.universal-links.core (ns status-im.utils.universal-links.core
(:require (:require [cljs.spec.alpha :as spec]
[taoensso.timbre :as log] [re-frame.core :as re-frame]
[re-frame.core :as re-frame] [status-im.accounts.db :as accounts.db]
[status-im.utils.config :as config] [status-im.chat.events :as chat.events]
[status-im.chat.events :as chat.events] [status-im.ui.components.list-selection :as list-selection]
[status-im.accounts.db :as accounts.db] [status-im.ui.components.react :as react]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.screens.add-new.new-chat.db :as new-chat.db]
[status-im.ui.components.react :as react] [status-im.ui.screens.navigation :as navigation]
[status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.config :as config]
[cljs.spec.alpha :as spec] [status-im.utils.fx :as fx]
[status-im.ui.screens.navigation :as navigation] [taoensso.timbre :as log]))
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db]))
;; TODO(yenda) investigate why `handle-universal-link` event is ;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link ;; dispatched 7 times for the same link
@ -37,21 +36,21 @@
;; as it is opened in safari on iOS ;; as it is opened in safari on iOS
(re-frame/dispatch [:handle-universal-link url]))) (re-frame/dispatch [:handle-universal-link url])))
(defn handle-browse [url cofx] (fx/defn handle-browse [cofx url]
(log/info "universal-links: handling browse " url) (log/info "universal-links: handling browse " url)
{:browser/show-browser-selection url}) {:browser/show-browser-selection url})
(defn handle-public-chat [public-chat cofx] (fx/defn handle-public-chat [cofx public-chat]
(log/info "universal-links: handling public chat " public-chat) (log/info "universal-links: handling public chat " public-chat)
(chat.events/create-new-public-chat public-chat false cofx)) (chat.events/create-new-public-chat cofx public-chat false))
(defn handle-view-profile [profile-id {:keys [db] :as cofx}] (fx/defn handle-view-profile [{:keys [db] :as cofx} profile-id]
(log/info "universal-links: handling view profile" profile-id) (log/info "universal-links: handling view profile" profile-id)
(if (new-chat.db/own-whisper-identity? db profile-id) (if (new-chat.db/own-whisper-identity? db profile-id)
(navigation/navigate-to-cofx :my-profile nil cofx) (navigation/navigate-to-cofx cofx :my-profile nil)
(chat.events/show-profile profile-id cofx))) (chat.events/show-profile cofx profile-id)))
(defn handle-extension [url cofx] (fx/defn handle-extension [cofx url]
(log/info "universal-links: handling url profile" url) (log/info "universal-links: handling url profile" url)
{:extension/load [url :extensions/stage]}) {:extension/load [url :extensions/stage]})
@ -65,45 +64,45 @@
(re-frame/dispatch [:handle-universal-link url]) (re-frame/dispatch [:handle-universal-link url])
(log/debug "universal-links: no url"))) (log/debug "universal-links: no url")))
(defn route-url (fx/defn route-url
"Match a url against a list of routes and handle accordingly" "Match a url against a list of routes and handle accordingly"
[url cofx] [cofx url]
(cond (cond
(match-url url public-chat-regex) (match-url url public-chat-regex)
(handle-public-chat (match-url url public-chat-regex) cofx) (handle-public-chat cofx (match-url url public-chat-regex))
(spec/valid? :global/public-key (match-url url profile-regex)) (spec/valid? :global/public-key (match-url url profile-regex))
(handle-view-profile (match-url url profile-regex) cofx) (handle-view-profile cofx (match-url url profile-regex))
(match-url url browse-regex) (match-url url browse-regex)
(handle-browse url cofx) (handle-browse cofx url)
(and config/extensions-enabled? (match-url url extension-regex)) (and config/extensions-enabled? (match-url url extension-regex))
(handle-extension url cofx) (handle-extension cofx url)
:else (handle-not-found url))) :else (handle-not-found url)))
(defn store-url-for-later (fx/defn store-url-for-later
"Store the url in the db to be processed on login" "Store the url in the db to be processed on login"
[url {:keys [db]}] [{:keys [db]} url]
(log/info :store-url-for-later) (log/info :store-url-for-later)
{:db (assoc db :universal-links/url url)}) {:db (assoc db :universal-links/url url)})
(defn handle-url (fx/defn handle-url
"Store url in the database if the user is not logged in, to be processed "Store url in the database if the user is not logged in, to be processed
on login, otherwise just handle it" on login, otherwise just handle it"
[url cofx] [cofx url]
(if (accounts.db/logged-in? cofx) (if (accounts.db/logged-in? cofx)
(route-url url cofx) (route-url cofx url)
(store-url-for-later url cofx))) (store-url-for-later cofx url)))
(defn process-stored-event (fx/defn process-stored-event
"Return an event description for processing a url if in the database" "Return an event description for processing a url if in the database"
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(when-let [url (:universal-links/url db)] (when-let [url (:universal-links/url db)]
(handlers-macro/merge-fx cofx (fx/merge cofx
{:db (dissoc db :universal-links/url)} {:db (dissoc db :universal-links/url)}
(handle-url url)))) (handle-url url))))
(defn unwrap-js-url [e] (defn unwrap-js-url [e]
(-> e (-> e

View File

@ -1,10 +1,7 @@
(ns status-im.utils.universal-links.events (ns status-im.utils.universal-links.events
(:require [re-frame.core :as re-frame] (:require [status-im.utils.handlers :as handlers]
[taoensso.timbre :as log] [status-im.utils.universal-links.core :as universal-links]
[status-im.utils.config :as config] [taoensso.timbre :as log]))
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.universal-links.core :as universal-links]))
(handlers/register-handler-fx (handlers/register-handler-fx
:handle-universal-link :handle-universal-link

View File

@ -44,19 +44,19 @@
(deftest set-phrase (deftest set-phrase
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater" (is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:passphrase-valid? true}}} :passphrase-valid? true}}}
(models/set-phrase (security/mask-data "game buzz method pretty olympic fat quit display velvet unveil marine crater") {:db {}}))) (models/set-phrase {:db {}} (security/mask-data "game buzz method pretty olympic fat quit display velvet unveil marine crater"))))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater" (is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:passphrase-valid? true}}} :passphrase-valid? true}}}
(models/set-phrase (security/mask-data "Game buzz method pretty Olympic fat quit DISPLAY velvet unveil marine crater") {:db {}}))) (models/set-phrase {:db {}} (security/mask-data "Game buzz method pretty Olympic fat quit DISPLAY velvet unveil marine crater"))))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater" (is (= {:db {:accounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
:passphrase-valid? true}}} :passphrase-valid? true}}}
(models/set-phrase (security/mask-data "game buzz method pretty zeus fat quit display velvet unveil marine crater") {:db {}}))) (models/set-phrase {:db {}} (security/mask-data "game buzz method pretty zeus fat quit display velvet unveil marine crater"))))
(is (= {:db {:accounts/recover {:passphrase " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater " (is (= {:db {:accounts/recover {:passphrase " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "
:passphrase-valid? true}}} :passphrase-valid? true}}}
(models/set-phrase (security/mask-data " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater ") {:db {}}))) (models/set-phrase {:db {}} (security/mask-data " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "))))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater" (is (= {:db {:accounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"
:passphrase-valid? false}}} :passphrase-valid? false}}}
(models/set-phrase (security/mask-data "game buzz method pretty 1234 fat quit display velvet unveil marine crater") {:db {}})))) (models/set-phrase {:db {}} (security/mask-data "game buzz method pretty 1234 fat quit display velvet unveil marine crater")))))
(deftest validate-phrase (deftest validate-phrase
(is (= {:db {:accounts/recover {:passphrase-error nil (is (= {:db {:accounts/recover {:passphrase-error nil
@ -75,13 +75,13 @@
(deftest set-password (deftest set-password
(is (= {:db {:accounts/recover {:password " " (is (= {:db {:accounts/recover {:password " "
:password-valid? false}}} :password-valid? false}}}
(models/set-password (security/mask-data " ") {:db {}}))) (models/set-password {:db {}} (security/mask-data " "))))
(is (= {:db {:accounts/recover {:password "abc" (is (= {:db {:accounts/recover {:password "abc"
:password-valid? false}}} :password-valid? false}}}
(models/set-password (security/mask-data "abc") {:db {}}))) (models/set-password {:db {}} (security/mask-data "abc"))))
(is (= {:db {:accounts/recover {:password "thisisapaswoord" (is (= {:db {:accounts/recover {:password "thisisapaswoord"
:password-valid? true}}} :password-valid? true}}}
(models/set-password (security/mask-data "thisisapaswoord") {:db {}})))) (models/set-password {:db {}} (security/mask-data "thisisapaswoord")))))
(deftest validate-password (deftest validate-password
(is (= {:db {:accounts/recover {:password " " (is (= {:db {:accounts/recover {:password " "

View File

@ -1,8 +1,7 @@
(ns status-im.test.browser.core (ns status-im.test.browser.core
(:require [cljs.test :refer-macros [deftest is testing]] (:require [cljs.test :refer-macros [deftest is testing]]
[status-im.browser.core :as browser] [status-im.browser.core :as browser]
[status-im.utils.types :as types] [status-im.utils.types :as types]))
[status-im.utils.handlers-macro :as handlers-macro]))
(defn has-navigated-to-browser? [result] (defn has-navigated-to-browser? [result]
(and (= (get result :status-im.ui.screens.navigation/navigate-to) (and (= (get result :status-im.ui.screens.navigation/navigate-to)
@ -26,7 +25,7 @@
dapp2-url "http://test2.com"] dapp2-url "http://test2.com"]
(testing "user opens a dapp" (testing "user opens a dapp"
(let [result-open (browser/open-url dapp1-url {:now 1})] (let [result-open (browser/open-url {:db {} :now 1} dapp1-url)]
(is (= dapp1-url (get-in result-open [:db :browser/options :browser-id])) (is (= dapp1-url (get-in result-open [:db :browser/options :browser-id]))
"browser-id should be dapp1-url") "browser-id should be dapp1-url")
(is (has-navigated-to-browser? result-open) (is (has-navigated-to-browser? result-open)
@ -42,8 +41,9 @@
"some properties of the browser are not correct") "some properties of the browser are not correct")
(testing "then a second dapp" (testing "then a second dapp"
(let [result-open-2 (browser/open-url dapp2-url {:db (:db result-open) (let [result-open-2 (browser/open-url {:db (:db result-open)
:now 2}) :now 2}
dapp2-url)
dapp2-host "test2.com"] dapp2-host "test2.com"]
(is (= dapp2-host (get-in result-open-2 [:db :browser/options :browser-id])) (is (= dapp2-host (get-in result-open-2 [:db :browser/options :browser-id]))
"browser-id should be dapp2 host") "browser-id should be dapp2 host")
@ -59,14 +59,15 @@
"some properties of the browser are not correct") "some properties of the browser are not correct")
(testing "then removes the second dapp" (testing "then removes the second dapp"
(let [result-remove-2 (browser/remove-browser dapp2-host {:db (:db result-open-2)})] (let [result-remove-2 (browser/remove-browser {:db (:db result-open-2)} dapp2-host)]
(is (= #{dapp1-url} (is (= #{dapp1-url}
(set (keys (get-in result-remove-2 [:db :browser/browsers])))) (set (keys (get-in result-remove-2 [:db :browser/browsers]))))
"the second dapp shouldn't be in the browser list anymore"))))) "the second dapp shouldn't be in the browser list anymore")))))
(testing "then opens the dapp again" (testing "then opens the dapp again"
(let [result-open-existing (browser/open-existing-browser dapp1-url {:db (:db result-open) (let [result-open-existing (browser/open-existing-browser {:db (:db result-open)
:now 2}) :now 2}
dapp1-url)
dapp1-url2 (str "http://" dapp1-url "/nav2") dapp1-url2 (str "http://" dapp1-url "/nav2")
browser (get-in result-open-existing [:db :browser/browsers dapp1-url])] browser (get-in result-open-existing [:db :browser/browsers dapp1-url])]
(is (not (has-wrong-properties? result-open-existing (is (not (has-wrong-properties? result-open-existing
@ -85,11 +86,11 @@
(testing "then navigates to a new url in the dapp" (testing "then navigates to a new url in the dapp"
(let [result-navigate (browser/navigation-state-changed (let [result-navigate (browser/navigation-state-changed
{:db (:db result-open-existing)
:now 4}
(clj->js {"url" dapp1-url2 (clj->js {"url" dapp1-url2
"loading" false}) "loading" false})
false false)]
{:db (:db result-open-existing)
:now 4})]
(is (not (has-wrong-properties? result-navigate (is (not (has-wrong-properties? result-navigate
dapp1-url dapp1-url
{:browser-id "cryptokitties.co" {:browser-id "cryptokitties.co"

View File

@ -2,36 +2,35 @@
(:require [cljs.test :refer-macros [deftest is testing]] (:require [cljs.test :refer-macros [deftest is testing]]
[status-im.browser.permissions :as permissions] [status-im.browser.permissions :as permissions]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.browser.core :as browser])) [status-im.browser.core :as browser]))
(deftest permissions-test (deftest permissions-test
(let [dapp-name "test.com" (let [dapp-name "test.com"
dapp-name2 "test2.org" dapp-name2 "test2.org"
cofx {:db (assoc-in (:db (browser/open-url dapp-name {})) cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
[:account/account :public-key] "public-key")}] [:account/account :public-key] "public-key")}]
(testing "dapps permissions are initialized" (testing "dapps permissions are initialized"
(is (zero? (count (get-in cofx [:db :dapps/permissions])))) (is (zero? (count (get-in cofx [:db :dapps/permissions]))))
(is (= dapp-name (get-in cofx [:db :browser/options :browser-id])))) (is (= dapp-name (get-in cofx [:db :browser/options :browser-id]))))
(testing "receiving an unsupported permission" (testing "receiving an unsupported permission"
(is (nil? (:browser/send-to-bridge (browser/process-bridge-message (types/clj->json {:type "status-api-request" (is (nil? (:browser/send-to-bridge (browser/process-bridge-message cofx
(types/clj->json {:type "status-api-request"
:host dapp-name :host dapp-name
:permissions ["FAKE_PERMISSION"]}) :permissions ["FAKE_PERMISSION"]}))))
cofx)))
"nothing should happen")) "nothing should happen"))
(testing "receiving a supported permission and an unsupported one" (testing "receiving a supported permission and an unsupported one"
(let [result-ask (browser/process-bridge-message (types/clj->json {:type "status-api-request" (let [result-ask (browser/process-bridge-message cofx
(types/clj->json {:type "status-api-request"
:host dapp-name :host dapp-name
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}) :permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}))]
cofx)]
(is (= (get-in result-ask [:db :browser/options :show-permission]) (is (= (get-in result-ask [:db :browser/options :show-permission])
{:requested-permission "CONTACT_CODE", :dapp-name "test.com"})) {:requested-permission "CONTACT_CODE", :dapp-name "test.com"}))
(is (zero? (count (get-in result-ask [:db :dapps/permissions])))) (is (zero? (count (get-in result-ask [:db :dapps/permissions]))))
(testing "then user accepts the supported permission" (testing "then user accepts the supported permission"
(let [accept-result (permissions/allow-permission dapp-name "CONTACT_CODE" {:db (:db result-ask)})] (let [accept-result (permissions/allow-permission {:db (:db result-ask)} dapp-name "CONTACT_CODE")]
(is (= (get-in accept-result [:browser/send-to-bridge :message]) (is (= (get-in accept-result [:browser/send-to-bridge :message])
{:type "status-api-success" {:type "status-api-success"
:data {"CONTACT_CODE" "public-key"} :data {"CONTACT_CODE" "public-key"}
@ -42,10 +41,10 @@
"the dapp should now have CONTACT_CODE permission") "the dapp should now have CONTACT_CODE permission")
(testing "then dapps asks for permission again" (testing "then dapps asks for permission again"
(let [result-ask-again (browser/process-bridge-message (types/clj->json {:type "status-api-request" (let [result-ask-again (browser/process-bridge-message {:db (:db accept-result)}
(types/clj->json {:type "status-api-request"
:host dapp-name :host dapp-name
:permissions ["CONTACT_CODE"]}) :permissions ["CONTACT_CODE"]}))]
{:db (:db accept-result)})]
(is (= (get-in result-ask-again (is (= (get-in result-ask-again
[:browser/send-to-bridge :message]) [:browser/send-to-bridge :message])
{:type "status-api-success" {:type "status-api-success"
@ -54,11 +53,11 @@
"the response should be immediatly sent to the bridge"))) "the response should be immediatly sent to the bridge")))
(testing "then user switch to another dapp that asks for permissions" (testing "then user switch to another dapp that asks for permissions"
(let [new-dapp (browser/open-url dapp-name2 {:db (:db accept-result)}) (let [new-dapp (browser/open-url {:db (:db accept-result)} dapp-name2)
result-ask2 (browser/process-bridge-message (types/clj->json {:type "status-api-request" result-ask2 (browser/process-bridge-message {:db (:db new-dapp)}
(types/clj->json {:type "status-api-request"
:host dapp-name2 :host dapp-name2
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}) :permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}))]
{:db (:db new-dapp)})]
(is (= (get-in result-ask2 [:db :dapps/permissions]) (is (= (get-in result-ask2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}}) {"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}})
"there should only be permissions for dapp-name at that point") "there should only be permissions for dapp-name at that point")
@ -67,7 +66,7 @@
"no message should be sent to the bridge") "no message should be sent to the bridge")
(testing "then user accepts permission for dapp-name2" (testing "then user accepts permission for dapp-name2"
(let [accept-result2 (permissions/allow-permission dapp-name2 "CONTACT_CODE" {:db (:db result-ask2)})] (let [accept-result2 (permissions/allow-permission {:db (:db result-ask2)} dapp-name2 "CONTACT_CODE")]
(is (= (get-in accept-result2 [:db :dapps/permissions]) (is (= (get-in accept-result2 [:db :dapps/permissions])
{"test.com" {:dapp "test.com" :permissions ["CONTACT_CODE"]} {"test.com" {:dapp "test.com" :permissions ["CONTACT_CODE"]}
"test2.org" {:dapp "test2.org" :permissions ["CONTACT_CODE"]}}) "test2.org" {:dapp "test2.org" :permissions ["CONTACT_CODE"]}})
@ -80,7 +79,7 @@
"the response should be sent to the bridge"))))) "the response should be sent to the bridge")))))
(testing "then user refuses the permission" (testing "then user refuses the permission"
(let [result-refuse (permissions/process-next-permission dapp-name {:db (:db result-ask)})] (let [result-refuse (permissions/process-next-permission {:db (:db result-ask)} dapp-name)]
(is (zero? (count (get-in result-refuse [:db :dapps/permissions]))) (is (zero? (count (get-in result-refuse [:db :dapps/permissions])))
"no permissions should be granted") "no permissions should be granted")
(is (nil? (get-in result-refuse [:browser/send-to-bridge :message])) (is (nil? (get-in result-refuse [:browser/send-to-bridge :message]))

View File

@ -65,7 +65,7 @@
(def AnotherTestCommandInstance (AnotherTestCommand.)) (def AnotherTestCommandInstance (AnotherTestCommand.))
(deftest load-commands-test (deftest load-commands-test
(let [fx (core/load-commands #{TestCommandInstance AnotherTestCommandInstance} {:db {}})] (let [fx (core/load-commands {:db {}} #{TestCommandInstance AnotherTestCommandInstance})]
(testing "Primary composite key index for command is correctly created" (testing "Primary composite key index for command is correctly created"
(is (= TestCommandInstance (is (= TestCommandInstance
(get-in fx [:db :id->command (get-in fx [:db :id->command
@ -94,7 +94,7 @@
(core/command-id AnotherTestCommandInstance)))))) (core/command-id AnotherTestCommandInstance))))))
(deftest chat-commands-test (deftest chat-commands-test
(let [fx (core/load-commands #{TestCommandInstance AnotherTestCommandInstance} {:db {}})] (let [fx (core/load-commands {:db {}} #{TestCommandInstance AnotherTestCommandInstance})]
(testing "That relevant commands are looked up for chat" (testing "That relevant commands are looked up for chat"
(is (= #{TestCommandInstance AnotherTestCommandInstance} (is (= #{TestCommandInstance AnotherTestCommandInstance}
(into #{} (into #{}

View File

@ -5,7 +5,7 @@
[status-im.chat.commands.input :as input])) [status-im.chat.commands.input :as input]))
(deftest selected-chat-command-test (deftest selected-chat-command-test
(let [fx (core/load-commands #{test-core/TestCommandInstance test-core/AnotherTestCommandInstance} {:db {}}) (let [fx (core/load-commands {:db {}} #{test-core/TestCommandInstance test-core/AnotherTestCommandInstance})
commands (core/chat-commands (get-in fx [:db :id->command]) commands (core/chat-commands (get-in fx [:db :id->command])
(get-in fx [:db :access-scope->command-id]) (get-in fx [:db :access-scope->command-id])
{:chat-id "contact"})] {:chat-id "contact"})]
@ -32,19 +32,16 @@
{:db {:chats {"test" {:input-text input-text}} {:db {:chats {"test" {:input-text input-text}}
:current-chat-id "test"}})] :current-chat-id "test"}})]
(is (= "/test-command first-value " (is (= "/test-command first-value "
(get-in (input/set-command-parameter (get-in (input/set-command-parameter (create-cofx "/test-command")
false 0 "first-value" false 0 "first-value")
(create-cofx "/test-command"))
[:db :chats "test" :input-text]))) [:db :chats "test" :input-text])))
(is (= "/test-command first-value second-value \"last value\"" (is (= "/test-command first-value second-value \"last value\""
(get-in (input/set-command-parameter (get-in (input/set-command-parameter (create-cofx "/test-command first-value edited \"last value\"")
false 1 "second-value" false 1 "second-value")
(create-cofx "/test-command first-value edited \"last value\""))
[:db :chats "test" :input-text]))) [:db :chats "test" :input-text])))
(is (= "/test-command first-value second-value \"last value\"" (is (= "/test-command first-value second-value \"last value\""
(get-in (input/set-command-parameter (get-in (input/set-command-parameter (create-cofx "/test-command first-value second-value")
false 2 "last value" false 2 "last value")
(create-cofx "/test-command first-value second-value"))
[:db :chats "test" :input-text])))))) [:db :chats "test" :input-text]))))))
(deftest parse-parameters-test (deftest parse-parameters-test

View File

@ -5,6 +5,6 @@
(deftest show-profile-test (deftest show-profile-test
(testing "Dafault behaviour: navigate to profile" (testing "Dafault behaviour: navigate to profile"
(let [{:keys [db]} (chat-events/show-profile (let [{:keys [db]} (chat-events/show-profile
"a" {:db {:navigation-stack '(:home)}}
{:db {:navigation-stack '(:home)}})] "a")]
(is (= "a" (:contacts/identity db)))))) (is (= "a" (:contacts/identity db))))))

View File

@ -12,7 +12,7 @@
cofx {:now "now" cofx {:now "now"
:db {:contacts/contacts {chat-id :db {:contacts/contacts {chat-id
{:name contact-name}}}} {:name contact-name}}}}
response (chat/upsert-chat chat-props cofx) response (chat/upsert-chat cofx chat-props)
actual-chat (get-in response [:db :chats chat-id]) actual-chat (get-in response [:db :chats chat-id])
store-chat-fx (:data-store/tx response)] store-chat-fx (:data-store/tx response)]
(testing "it adds the chat to the chats collection" (testing "it adds the chat to the chats collection"
@ -36,7 +36,7 @@
:extra-prop "some"} :extra-prop "some"}
cofx {:db {:chats {chat-id {:is-active true cofx {:db {:chats {chat-id {:is-active true
:name "old-name"}}}} :name "old-name"}}}}
response (chat/upsert-chat chat-props cofx) response (chat/upsert-chat cofx chat-props)
actual-chat (get-in response [:db :chats chat-id]) actual-chat (get-in response [:db :chats chat-id])
store-chat-fx (:data-store/tx response)] store-chat-fx (:data-store/tx response)]
(testing "it adds the chat to the chats collection" (testing "it adds the chat to the chats collection"
@ -57,16 +57,16 @@
:db {:chats {chat-id {:is-active false :db {:chats {chat-id {:is-active false
:name "old-name"}}}}] :name "old-name"}}}}]
(testing "it updates it if is-active is passed" (testing "it updates it if is-active is passed"
(is (get-in (chat/upsert-chat (assoc chat-props :is-active true) cofx) [:db :chats chat-id :is-active]))) (is (get-in (chat/upsert-chat cofx (assoc chat-props :is-active true)) [:db :chats chat-id :is-active])))
(testing "it returns the db unchanged" (testing "it returns the db unchanged"
(is (= {:db (:db cofx)} (chat/upsert-chat chat-props cofx))))))) (is (= {:db (:db cofx)} (chat/upsert-chat cofx chat-props)))))))
(deftest add-group-chat (deftest add-group-chat
(let [chat-id "chat-id" (let [chat-id "chat-id"
chat-name "chat-name" chat-name "chat-name"
admin "admin" admin "admin"
participants ["a"] participants ["a"]
fx (chat/add-group-chat chat-id chat-name admin participants {}) fx (chat/add-group-chat {:db {}} chat-id chat-name admin participants)
store-fx (:data-store/tx fx) store-fx (:data-store/tx fx)
group-chat (get-in fx [:db :chats chat-id])] group-chat (get-in fx [:db :chats chat-id])]
(testing "it saves the chat in the database" (testing "it saves the chat in the database"
@ -86,7 +86,7 @@
(deftest add-public-chat (deftest add-public-chat
(let [topic "topic" (let [topic "topic"
fx (chat/add-public-chat topic {}) fx (chat/add-public-chat {:db {}} topic)
store-fx (:data-store/tx fx) store-fx (:data-store/tx fx)
chat (get-in fx [:db :chats topic])] chat (get-in fx [:db :chats topic])]
(testing "it saves the chat in the database" (testing "it saves the chat in the database"
@ -111,38 +111,38 @@
:unviewed-messages #{"3"} :unviewed-messages #{"3"}
:not-loaded-message-ids #{"2" "3"}}}}}] :not-loaded-message-ids #{"2" "3"}}}}}]
(testing "it deletes all the messages" (testing "it deletes all the messages"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (= {} (get-in actual [:db :chats chat-id :messages]))))) (is (= {} (get-in actual [:db :chats chat-id :messages])))))
(testing "it deletes all the message groups" (testing "it deletes all the message groups"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (= {} (get-in actual [:db :chats chat-id :message-groups]))))) (is (= {} (get-in actual [:db :chats chat-id :message-groups])))))
(testing "it deletes unviewed messages set" (testing "it deletes unviewed messages set"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (= #{} (get-in actual [:db :chats chat-id :unviewed-messages]))))) (is (= #{} (get-in actual [:db :chats chat-id :unviewed-messages])))))
(testing "it deletes not loaded message ids set" (testing "it deletes not loaded message ids set"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (= #{} (get-in actual [:db :chats chat-id :not-loaded-message-ids]))))) (is (= #{} (get-in actual [:db :chats chat-id :not-loaded-message-ids])))))
(testing "it sets a deleted-at-clock-value equal to the last message clock-value" (testing "it sets a deleted-at-clock-value equal to the last message clock-value"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))) (is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
(testing "it does not override the deleted-at-clock-value when there are no messages" (testing "it does not override the deleted-at-clock-value when there are no messages"
(let [actual (chat/clear-history chat-id (let [actual (chat/clear-history (update-in cofx
(update-in cofx
[:db :chats chat-id] [:db :chats chat-id]
assoc assoc
:messages {} :messages {}
:deleted-at-clock-value 100))] :deleted-at-clock-value 100)
chat-id)]
(is (= 100 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))) (is (= 100 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
(testing "it set the deleted-at-clock-value to now the chat has no messages nor previous deleted-at" (testing "it set the deleted-at-clock-value to now the chat has no messages nor previous deleted-at"
(with-redefs [utils.clocks/send (constantly 42)] (with-redefs [utils.clocks/send (constantly 42)]
(let [actual (chat/clear-history chat-id (let [actual (chat/clear-history (update-in cofx
(update-in cofx
[:db :chats chat-id] [:db :chats chat-id]
assoc assoc
:messages {}))] :messages {})
chat-id)]
(is (= 42 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))) (is (= 42 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))))
(testing "it adds the relevant transactions for realm" (testing "it adds the relevant transactions for realm"
(let [actual (chat/clear-history chat-id cofx)] (let [actual (chat/clear-history cofx chat-id)]
(is (:data-store/tx actual)) (is (:data-store/tx actual))
(is (= 2 (count (:data-store/tx actual)))))))) (is (= 2 (count (:data-store/tx actual))))))))
@ -153,37 +153,37 @@
"2" {:clock-value 10} "2" {:clock-value 10}
"3" {:clock-value 2}}}}}}] "3" {:clock-value 2}}}}}}]
(testing "it deletes all the messages" (testing "it deletes all the messages"
(let [actual (chat/remove-chat chat-id cofx)] (let [actual (chat/remove-chat cofx chat-id)]
(is (= {} (get-in actual [:db :chats chat-id :messages]))))) (is (= {} (get-in actual [:db :chats chat-id :messages])))))
(testing "it sets a deleted-at-clock-value equal to the last message clock-value" (testing "it sets a deleted-at-clock-value equal to the last message clock-value"
(let [actual (chat/remove-chat chat-id cofx)] (let [actual (chat/remove-chat cofx chat-id)]
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))) (is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
(testing "it sets the chat as inactive" (testing "it sets the chat as inactive"
(let [actual (chat/remove-chat chat-id cofx)] (let [actual (chat/remove-chat cofx chat-id)]
(is (= false (get-in actual [:db :chats chat-id :is-active]))))) (is (= false (get-in actual [:db :chats chat-id :is-active])))))
(testing "it removes it from transport if it's a public chat" (testing "it removes it from transport if it's a public chat"
(let [actual (chat/remove-chat chat-id (let [actual (chat/remove-chat (update-in
(update-in
cofx cofx
[:db :chats chat-id] [:db :chats chat-id]
assoc assoc
:group-chat true :group-chat true
:public? true))] :public? true)
chat-id)]
(is (not (get-in actual [:db :transport/chats chat-id]))))) (is (not (get-in actual [:db :transport/chats chat-id])))))
(testing "it sends a leave group request if it's a group-chat" (testing "it sends a leave group request if it's a group-chat"
(let [actual (chat/remove-chat chat-id (let [actual (chat/remove-chat (assoc-in
(assoc-in
cofx cofx
[:db :chats chat-id :group-chat] [:db :chats chat-id :group-chat]
true))] true)
chat-id)]
(is (:shh/post actual)) (is (:shh/post actual))
(testing "it does not remove transport, only after send is successful" (testing "it does not remove transport, only after send is successful"
(is (get-in actual [:db :transport/chats chat-id]))))) (is (get-in actual [:db :transport/chats chat-id])))))
(testing "it does not remove it from transport if it's a one-to-one" (testing "it does not remove it from transport if it's a one-to-one"
(let [actual (chat/remove-chat chat-id cofx)] (let [actual (chat/remove-chat cofx chat-id)]
(is (get-in actual [:db :transport/chats chat-id])))) (is (get-in actual [:db :transport/chats chat-id]))))
(testing "it adds the relevant transactions for realm" (testing "it adds the relevant transactions for realm"
(let [actual (chat/remove-chat chat-id cofx)] (let [actual (chat/remove-chat cofx chat-id)]
(is (:data-store/tx actual)) (is (:data-store/tx actual))
(is (= 3 (count (:data-store/tx actual)))))))) (is (= 3 (count (:data-store/tx actual))))))))
@ -191,25 +191,25 @@
(let [chat-id "1"] (let [chat-id "1"]
(testing "it returns true if it's a group chat" (testing "it returns true if it's a group chat"
(let [cofx {:db {:chats {chat-id {:group-chat true}}}}] (let [cofx {:db {:chats {chat-id {:group-chat true}}}}]
(is (chat/multi-user-chat? chat-id cofx)))) (is (chat/multi-user-chat? cofx chat-id))))
(testing "it returns true if it's a public chat" (testing "it returns true if it's a public chat"
(let [cofx {:db {:chats {chat-id {:public? true :group-chat true}}}}] (let [cofx {:db {:chats {chat-id {:public? true :group-chat true}}}}]
(is (chat/multi-user-chat? chat-id cofx)))) (is (chat/multi-user-chat? cofx chat-id))))
(testing "it returns false if it's a 1-to-1 chat" (testing "it returns false if it's a 1-to-1 chat"
(let [cofx {:db {:chats {chat-id {}}}}] (let [cofx {:db {:chats {chat-id {}}}}]
(is (not (chat/multi-user-chat? chat-id cofx))))))) (is (not (chat/multi-user-chat? cofx chat-id)))))))
(deftest group-chat? (deftest group-chat?
(let [chat-id "1"] (let [chat-id "1"]
(testing "it returns true if it's a group chat" (testing "it returns true if it's a group chat"
(let [cofx {:db {:chats {chat-id {:group-chat true}}}}] (let [cofx {:db {:chats {chat-id {:group-chat true}}}}]
(is (chat/group-chat? chat-id cofx)))) (is (chat/group-chat? cofx chat-id))))
(testing "it returns false if it's a public chat" (testing "it returns false if it's a public chat"
(let [cofx {:db {:chats {chat-id {:public? true :group-chat true}}}}] (let [cofx {:db {:chats {chat-id {:public? true :group-chat true}}}}]
(is (not (chat/group-chat? chat-id cofx))))) (is (not (chat/group-chat? cofx chat-id)))))
(testing "it returns false if it's a 1-to-1 chat" (testing "it returns false if it's a 1-to-1 chat"
(let [cofx {:db {:chats {chat-id {}}}}] (let [cofx {:db {:chats {chat-id {}}}}]
(is (not (chat/group-chat? chat-id cofx))))))) (is (not (chat/group-chat? cofx chat-id)))))))
(def test-db (def test-db
{:current-public-key "me" {:current-public-key "me"
@ -248,7 +248,7 @@
(deftest mark-messages-seen (deftest mark-messages-seen
(testing "Marking messages seen correctly marks loaded messages as seen and updates absolute unviewed set" (testing "Marking messages seen correctly marks loaded messages as seen and updates absolute unviewed set"
(let [fx (chat/mark-messages-seen "status" {:db test-db}) (let [fx (chat/mark-messages-seen {:db test-db} "status")
me (:current-public-key test-db)] me (:current-public-key test-db)]
(is (= '(:seen :seen :seen) (is (= '(:seen :seen :seen)
(map (fn [[_ v]] (map (fn [[_ v]]
@ -259,9 +259,9 @@
(is (= #{"3" "2" "1"} (get-in fx [:db :chats "status" :unviewed-messages]))))) (is (= #{"3" "2" "1"} (get-in fx [:db :chats "status" :unviewed-messages])))))
(testing "With empty unviewed set, no effects are produced" (testing "With empty unviewed set, no effects are produced"
(is (= nil (chat/mark-messages-seen "opened" {:db test-db})))) (is (= nil (chat/mark-messages-seen {:db test-db} "opened"))))
(testing "For 1-1 chat, we send seen messages confirmation to the recipient as well" (testing "For 1-1 chat, we send seen messages confirmation to the recipient as well"
(is (= #{"4" "5" "6"} (is (= #{"4" "5" "6"}
(set (get-in (chat/mark-messages-seen "1-1" {:db test-db}) (set (get-in (chat/mark-messages-seen {:db test-db} "1-1")
[:shh/post 0 :message :payload :message-ids])))))) [:shh/post 0 :message :payload :message-ids]))))))

View File

@ -37,7 +37,7 @@
(testing "New messages are grouped/sorted correctly, hidden messages are not grouped" (testing "New messages are grouped/sorted correctly, hidden messages are not grouped"
(is (= '(2 3) (is (= '(2 3)
(map :message-id (map :message-id
(-> (get-in (loading/group-chat-messages "chat-id" new-messages cofx) (-> (get-in (loading/group-chat-messages cofx "chat-id" new-messages)
[:db :chats "chat-id" :message-groups]) [:db :chats "chat-id" :message-groups])
first first
second))))))) second)))))))

View File

@ -48,13 +48,12 @@
:current-chat-id "chat-id" :current-chat-id "chat-id"
:chats {"chat-id" {:messages {}}}}] :chats {"chat-id" {:messages {}}}}]
(testing "a message coming from you!" (testing "a message coming from you!"
(let [actual (message/receive (let [actual (message/receive {:db db}
{:from "me" {:from "me"
:message-id "id" :message-id "id"
:chat-id "chat-id" :chat-id "chat-id"
:content "b" :content "b"
:clock-value 1} :clock-value 1})
{:db db})
message (get-in actual [:db :chats "chat-id" :messages "id"]) message (get-in actual [:db :chats "chat-id" :messages "id"])
status (get-in actual [:db :chats "chat-id" :message-statuses "id" "me" :status])] status (get-in actual [:db :chats "chat-id" :message-statuses "id" "me" :status])]
(testing "it adds the message" (testing "it adds the message"
@ -71,7 +70,7 @@
(is (= :sent status))))))) (is (= :sent status)))))))
(deftest receive-send-seen (deftest receive-send-seen
(let [db {:db {:chats {"chat-id" {}} (let [cofx {:db {:chats {"chat-id" {}}
:account/account {:public-key "a"} :account/account {:public-key "a"}
:current-chat-id "chat-id" :current-chat-id "chat-id"
:view-id :chat}} :view-id :chat}}
@ -83,23 +82,20 @@
extract-seen (comp :payload :message first :shh/post)] extract-seen (comp :payload :message first :shh/post)]
(testing "it send a seen message when the chat is 1-to-1 and is open" (testing "it send a seen message when the chat is 1-to-1 and is open"
(is (instance? protocol/MessagesSeen (is (instance? protocol/MessagesSeen
(extract-seen (message/receive message db)))) (extract-seen (message/receive cofx message))))
(is (= #{"1"} (:message-ids (extract-seen (message/receive message db)))))) (is (= #{"1"} (:message-ids (extract-seen (message/receive cofx message))))))
(testing "it does not send any when the chat is public" (testing "it does not send any when the chat is public"
(is (nil? (extract-seen (is (nil? (extract-seen
(message/receive (message/receive (assoc-in cofx [:db :chats "chat-id" :public?] true)
message message)))))
(assoc-in db [:db :chats "chat-id" :public?] true))))))
(testing "it does not send any when we are in a different chat" (testing "it does not send any when we are in a different chat"
(is (nil? (extract-seen (is (nil? (extract-seen
(message/receive (message/receive (assoc-in cofx [:db :current-chat-id] :different)
message message)))))
(assoc-in db [:db :current-chat-id] :different))))))
(testing "it does not send any when we are not in a chat view" (testing "it does not send any when we are not in a chat view"
(is (nil? (extract-seen (is (nil? (extract-seen
(message/receive (message/receive (assoc-in cofx [:db :view-id] :home)
message message)))))))
(assoc-in db [:db :view-id] :home))))))))
(deftest delete-message (deftest delete-message
(let [timestamp (time/now) (let [timestamp (time/now)
@ -118,8 +114,8 @@
:clock-value 0 :clock-value 0
:timestamp timestamp}} :timestamp timestamp}}
:message-groups {"datetime-today" '({:message-id 0})}}}}} :message-groups {"datetime-today" '({:message-id 0})}}}}}
fx1 (message/delete-message "chat-id" 1 cofx1) fx1 (message/delete-message cofx1 "chat-id" 1)
fx2 (message/delete-message "chat-id" 0 cofx2)] fx2 (message/delete-message cofx2 "chat-id" 0)]
(testing "Deleting message deletes it along with all references" (testing "Deleting message deletes it along with all references"
(is (= '(0) (is (= '(0)
(keys (get-in fx1 [:db :chats "chat-id" :messages])))) (keys (get-in fx1 [:db :chats "chat-id" :messages]))))

View File

@ -8,39 +8,39 @@
:confirmation [] :confirmation []
:status nil :status nil
:enter-step :original}}}} :enter-step :original}}}}
(hardwallet/process-pin-input 1 (hardwallet/process-pin-input {:db {:hardwallet {:pin {:original []
:original
{:db {:hardwallet {:pin {:original []
:confirmation [] :confirmation []
:enter-step :original}}}})))) :enter-step :original}}}}
1
:original))))
(testing "first 6 numbers entered" (testing "first 6 numbers entered"
(is (= {:db {:hardwallet {:pin {:original [1 2 3 4 5 6] (is (= {:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation [] :confirmation []
:status nil :status nil
:enter-step :confirmation}}}} :enter-step :confirmation}}}}
(hardwallet/process-pin-input 6 (hardwallet/process-pin-input {:db {:hardwallet {:pin {:original [1 2 3 4 5]
:original
{:db {:hardwallet {:pin {:original [1 2 3 4 5]
:confirmation [] :confirmation []
:enter-step :original}}}})))) :enter-step :original}}}}
6
:original))))
(testing "confirmation entered" (testing "confirmation entered"
(is (= {:db {:hardwallet {:pin {:original [1 2 3 4 5 6] (is (= {:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation [1 2 3 4 5 6] :confirmation [1 2 3 4 5 6]
:enter-step :confirmation :enter-step :confirmation
:status :validating}}}} :status :validating}}}}
(hardwallet/process-pin-input 6 (hardwallet/process-pin-input {:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation
{:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation [1 2 3 4 5] :confirmation [1 2 3 4 5]
:enter-step :confirmation}}}})))) :enter-step :confirmation}}}}
6
:confirmation))))
(testing "confirmation doesn't match" (testing "confirmation doesn't match"
(is (= {:db {:hardwallet {:pin {:original [] (is (= {:db {:hardwallet {:pin {:original []
:confirmation [] :confirmation []
:enter-step :original :enter-step :original
:error :t/pin-mismatch :error :t/pin-mismatch
:status :error}}}} :status :error}}}}
(hardwallet/process-pin-input 7 (hardwallet/process-pin-input {:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation
{:db {:hardwallet {:pin {:original [1 2 3 4 5 6]
:confirmation [1 2 3 4 5] :confirmation [1 2 3 4 5]
:enter-step :confirmation}}}}))))) :enter-step :confirmation}}}}
7
:confirmation)))))

View File

@ -5,6 +5,6 @@
(deftest initialize-account-db (deftest initialize-account-db
(testing "it preserves universal-links/url" (testing "it preserves universal-links/url"
(is (= "some-url" (get-in (init/initialize-account-db (is (= "some-url" (get-in (init/initialize-account-db
"address" {:db {:universal-links/url "some-url"}}
{:db {:universal-links/url "some-url"}}) "address")
[:db :universal-links/url]))))) [:db :universal-links/url])))))

View File

@ -47,20 +47,20 @@
(testing "correct name" (testing "correct name"
(is (= {:db {:mailservers/manage {:name {:value "value" (is (= {:db {:mailservers/manage {:name {:value "value"
:error false}}}} :error false}}}}
(mailserver/set-input :name "value" {})))) (mailserver/set-input {:db {}} :name "value"))))
(testing "blank name" (testing "blank name"
(is (= {:db {:mailservers/manage {:name {:value "" (is (= {:db {:mailservers/manage {:name {:value ""
:error true}}}} :error true}}}}
(mailserver/set-input :name "" {}))))) (mailserver/set-input {:db {}} :name "")))))
(testing "it validates enodes url" (testing "it validates enodes url"
(testing "correct url" (testing "correct url"
(is (= {:db {:mailservers/manage {:url {:value valid-enode-url (is (= {:db {:mailservers/manage {:url {:value valid-enode-url
:error false}}}} :error false}}}}
(mailserver/set-input :url valid-enode-url {})))) (mailserver/set-input {:db {}} :url valid-enode-url))))
(testing "broken url" (testing "broken url"
(is (= {:db {:mailservers/manage {:url {:value "broken" (is (= {:db {:mailservers/manage {:url {:value "broken"
:error true}}}} :error true}}}}
(mailserver/set-input :url "broken" {})))))) (mailserver/set-input {:db {}} :url "broken"))))))
(deftest edit-mailserver (deftest edit-mailserver
(let [db {:inbox/wnodes (let [db {:inbox/wnodes
@ -70,7 +70,7 @@
:name "name"}}}} :name "name"}}}}
cofx {:db db}] cofx {:db db}]
(testing "when no id is given" (testing "when no id is given"
(let [actual (mailserver/edit nil cofx)] (let [actual (mailserver/edit cofx nil)]
(testing "it resets :mailserver/manage" (testing "it resets :mailserver/manage"
(is (= {:id {:value nil (is (= {:id {:value nil
:error false} :error false}
@ -80,11 +80,11 @@
:error true}} :error true}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver] (is (= :edit-mailserver
(-> actual :dispatch)))))) (:status-im.ui.screens.navigation/navigate-to actual))))))
(testing "when an id is given" (testing "when an id is given"
(testing "when the wnode is in the list" (testing "when the wnode is in the list"
(let [actual (mailserver/edit "a" cofx)] (let [actual (mailserver/edit cofx "a")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value "a" (is (= {:id {:value "a"
:error false} :error false}
@ -94,10 +94,10 @@
:error false}} :error false}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver] (is (= :edit-mailserver
(-> actual :dispatch)))))) (:status-im.ui.screens.navigation/navigate-to actual))))))
(testing "when the wnode is not in the list" (testing "when the wnode is not in the list"
(let [actual (mailserver/edit "not-existing" cofx)] (let [actual (mailserver/edit cofx "not-existing")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value nil (is (= {:id {:value nil
:error false} :error false}
@ -107,22 +107,22 @@
:error true}} :error true}}
(-> actual :db :mailservers/manage)))) (-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view" (testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver] (is (= :edit-mailserver
(-> actual :dispatch))))))))) (:status-im.ui.screens.navigation/navigate-to actual)))))))))
(deftest connected-mailserver (deftest connected-mailserver
(testing "it returns true when set in inbox/current-id" (testing "it returns true when set in inbox/current-id"
(let [cofx {:db {:inbox/current-id "a"}}] (let [cofx {:db {:inbox/current-id "a"}}]
(is (mailserver/connected? "a" cofx)))) (is (mailserver/connected? cofx "a"))))
(testing "it returns false otherwise" (testing "it returns false otherwise"
(is (not (mailserver/connected? "a" {}))))) (is (not (mailserver/connected? {:db {}} "a")))))
(deftest fetch-mailserver (deftest fetch-mailserver
(testing "it fetches the mailserver from the db" (testing "it fetches the mailserver from the db"
(let [cofx {:db {:inbox/wnodes {:eth.beta {"a" {:id "a" (let [cofx {:db {:inbox/wnodes {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}] :address "enode://old-id:old-password@url:port"}}}}}]
(is (mailserver/fetch "a" cofx))))) (is (mailserver/fetch cofx "a")))))
(deftest fetch-current-mailserver (deftest fetch-current-mailserver
(testing "it fetches the mailserver from the db with corresponding id" (testing "it fetches the mailserver from the db with corresponding id"
@ -187,9 +187,9 @@
:name "old-name" :name "old-name"
:user-defined true :user-defined true
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete "a" cofx)] actual (mailserver/delete cofx "a")]
(testing "it removes the mailserver from the list" (testing "it removes the mailserver from the list"
(is (not (mailserver/fetch "a" actual)))) (is (not (mailserver/fetch actual "a"))))
(testing "it stores it in the db" (testing "it stores it in the db"
(is (= 1 (count (:data-store/tx actual))))))) (is (= 1 (count (:data-store/tx actual)))))))
(testing "the mailserver is not user-defined" (testing "the mailserver is not user-defined"
@ -197,7 +197,7 @@
:db {:inbox/wnodes {:eth.beta {"a" {:id "a" :db {:inbox/wnodes {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete "a" cofx)] actual (mailserver/delete cofx "a")]
(testing "it does not delete the mailserver" (testing "it does not delete the mailserver"
(is (= {:dispatch [:navigate-back]} actual))))) (is (= {:dispatch [:navigate-back]} actual)))))
(testing "the user is connected to the mailserver" (testing "the user is connected to the mailserver"
@ -205,7 +205,7 @@
:db {:inbox/wnodes {:eth.beta {"a" {:id "a" :db {:inbox/wnodes {:eth.beta {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete "a" cofx)] actual (mailserver/delete cofx "a")]
(testing "it does not remove the mailserver from the list" (testing "it does not remove the mailserver from the list"
(is (= {:dispatch [:navigate-back]} actual)))))) (is (= {:dispatch [:navigate-back]} actual))))))

View File

@ -46,20 +46,20 @@
(testing "correct name" (testing "correct name"
(is (= {:db {:bootnodes/manage {:name {:value "value" (is (= {:db {:bootnodes/manage {:name {:value "value"
:error false}}}} :error false}}}}
(model/set-input :name "value" {})))) (model/set-input {:db {}} :name "value"))))
(testing "blank name" (testing "blank name"
(is (= {:db {:bootnodes/manage {:name {:value "" (is (= {:db {:bootnodes/manage {:name {:value ""
:error true}}}} :error true}}}}
(model/set-input :name "" {}))))) (model/set-input {:db {}} :name "")))))
(testing "it validates bootnode url" (testing "it validates bootnode url"
(testing "correct url" (testing "correct url"
(is (= {:db {:bootnodes/manage {:url {:value valid-bootnode-address (is (= {:db {:bootnodes/manage {:url {:value valid-bootnode-address
:error false}}}} :error false}}}}
(model/set-input :url valid-bootnode-address {})))) (model/set-input {:db {}} :url valid-bootnode-address))))
(testing "broken url" (testing "broken url"
(is (= {:db {:bootnodes/manage {:url {:value "broken" (is (= {:db {:bootnodes/manage {:url {:value "broken"
:error true}}}} :error true}}}}
(model/set-input :url "broken" {})))))) (model/set-input {:db {}} :url "broken"))))))
(deftest edit-bootnode (deftest edit-bootnode
(let [db {:network "mainnet_rpc" (let [db {:network "mainnet_rpc"
@ -71,7 +71,7 @@
:address valid-bootnode-address}}}}} :address valid-bootnode-address}}}}}
cofx {:db db}] cofx {:db db}]
(testing "when no id is given" (testing "when no id is given"
(let [actual (model/edit nil cofx)] (let [actual (model/edit cofx nil)]
(testing "it resets :bootnodes/manage" (testing "it resets :bootnodes/manage"
(is (= {:id {:value nil (is (= {:id {:value nil
:error false} :error false}
@ -85,7 +85,7 @@
(-> actual :dispatch)))))) (-> actual :dispatch))))))
(testing "when an id is given" (testing "when an id is given"
(testing "when the bootnode is in the list" (testing "when the bootnode is in the list"
(let [actual (model/edit "a" cofx)] (let [actual (model/edit cofx "a")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value "a" (is (= {:id {:value "a"
:error false} :error false}
@ -98,7 +98,7 @@
(is (= [:navigate-to :edit-bootnode] (is (= [:navigate-to :edit-bootnode]
(-> actual :dispatch)))))) (-> actual :dispatch))))))
(testing "when the bootnode is not in the list" (testing "when the bootnode is not in the list"
(let [actual (model/edit "not-existing" cofx)] (let [actual (model/edit cofx "not-existing")]
(testing "it populates the fields with the correct values" (testing "it populates the fields with the correct values"
(is (= {:id {:value nil (is (= {:id {:value nil
:error false} :error false}
@ -118,7 +118,7 @@
{"a" {:id "a" {"a" {:id "a"
:name "name" :name "name"
:address "enode://old-id:old-password@url:port"}}}}}}] :address "enode://old-id:old-password@url:port"}}}}}}]
(is (model/fetch "a" cofx))))) (is (model/fetch cofx "a")))))
(deftest custom-bootnodes-in-use? (deftest custom-bootnodes-in-use?
(testing "is on the same network" (testing "is on the same network"
@ -149,9 +149,9 @@
:address "enode://old-id:old-password@url:port"}}} :address "enode://old-id:old-password@url:port"}}}
:settings {:bootnodes :settings {:bootnodes
{"mainnnet_rpc" true}}}}} {"mainnnet_rpc" true}}}}}
actual (model/delete "b" cofx)] actual (model/delete cofx "b")]
(testing "it does not removes the bootnode" (testing "it does not removes the bootnode"
(is (model/fetch "a" actual))))) (is (model/fetch actual "a")))))
(testing "existing bootnode" (testing "existing bootnode"
(let [cofx {:db {:network "mainnet_rpc" (let [cofx {:db {:network "mainnet_rpc"
:account/account {:bootnodes {"mainnet_rpc" :account/account {:bootnodes {"mainnet_rpc"
@ -160,8 +160,9 @@
:address "enode://old-id:old-password@url:port"}}} :address "enode://old-id:old-password@url:port"}}}
:settings {:bootnodes :settings {:bootnodes
{"mainnnet_rpc" true}}}}} {"mainnnet_rpc" true}}}}}
actual (model/delete "a" cofx)] actual (model/delete cofx "a")]
(testing "it removes the bootnode" (testing "it removes the bootnode"
(is (not (model/fetch "a" actual)))) (is (not (model/fetch actual "a"))))
(testing "it updates the db" (testing "it updates the db"
(is (= 1 (count (:data-store/base-tx actual)))))))) (is (= 1 (count (:data-store/base-tx actual))))))))

View File

@ -86,13 +86,13 @@
:error true} :error true}
:chain {:value "mainnet" :chain {:value "mainnet"
:error false}}}} :error false}}}}
(model/set-input :url "http://valid.com" (model/set-input {:db {:networks/manage {:url {:value "something"
{:db {:networks/manage {:url {:value "something"
:error true} :error true}
:name {:value "" :name {:value ""
:error false} :error false}
:chain {:value "mainnet" :chain {:value "mainnet"
:error false}}}}))))) :error false}}}}
:url "http://valid.com")))))
(deftest save (deftest save
(testing "it does not save a network with an invalid url" (testing "it does not save a network with an invalid url"

View File

@ -14,33 +14,33 @@
cofx {:db {:accounts/accounts {address {:installation-id "id"}}}}] cofx {:db {:accounts/accounts {address {:installation-id "id"}}}}]
(testing "installation-id" (testing "installation-id"
(testing "the user is not logged in" (testing "the user is not logged in"
(let [actual (parse-node-config (node/start nil cofx))] (let [actual (parse-node-config (node/start cofx nil))]
(is (not (:InstallationID actual))))) (is (not (:InstallationID actual)))))
(testing "the user is logged in" (testing "the user is logged in"
(let [actual (parse-node-config (node/start address cofx))] (let [actual (parse-node-config (node/start cofx address))]
(is (= "id" (:InstallationID actual)))))) (is (= "id" (:InstallationID actual))))))
(testing "pfs & group chats disabled" (testing "pfs & group chats disabled"
(with-redefs [config/pfs-encryption-enabled? false (with-redefs [config/pfs-encryption-enabled? false
config/group-chats-enabled? false] config/group-chats-enabled? false]
(testing "the user is not logged in" (testing "the user is not logged in"
(let [actual (parse-node-config (node/start nil cofx))] (let [actual (parse-node-config (node/start cofx nil))]
(is (not (:PFSEnabled actual))))) (is (not (:PFSEnabled actual)))))
(testing "the user is logged in" (testing "the user is logged in"
(let [actual (parse-node-config (node/start address cofx))] (let [actual (parse-node-config (node/start cofx address))]
(is (not (:PFSEnabled actual)))))) (is (not (:PFSEnabled actual))))))
(testing "pfs is enabled" (testing "pfs is enabled"
(with-redefs [config/pfs-encryption-enabled? true] (with-redefs [config/pfs-encryption-enabled? true]
(testing "the user is not logged in" (testing "the user is not logged in"
(let [actual (parse-node-config (node/start nil cofx))] (let [actual (parse-node-config (node/start cofx nil))]
(is (not (:PFSEnabled actual))))) (is (not (:PFSEnabled actual)))))
(testing "the user is logged in" (testing "the user is logged in"
(let [actual (parse-node-config (node/start address cofx))] (let [actual (parse-node-config (node/start cofx address))]
(is (:PFSEnabled actual)))))) (is (:PFSEnabled actual))))))
(testing "group chats is enabled" (testing "group chats is enabled"
(with-redefs [config/group-chats-enabled? true] (with-redefs [config/group-chats-enabled? true]
(testing "the user is not logged in" (testing "the user is not logged in"
(let [actual (parse-node-config (node/start nil cofx))] (let [actual (parse-node-config (node/start cofx nil))]
(is (not (:PFSEnabled actual))))) (is (not (:PFSEnabled actual)))))
(testing "the user is logged in" (testing "the user is logged in"
(let [actual (parse-node-config (node/start address cofx))] (let [actual (parse-node-config (node/start cofx address))]
(is (:PFSEnabled actual))))))))) (is (:PFSEnabled actual)))))))))

View File

@ -33,7 +33,6 @@
[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]
[status-im.test.utils.handlers-macro]
[status-im.test.utils.clocks] [status-im.test.utils.clocks]
[status-im.test.utils.ethereum.eip681] [status-im.test.utils.ethereum.eip681]
[status-im.test.utils.ethereum.core] [status-im.test.utils.ethereum.core]
@ -98,7 +97,6 @@
'status-im.test.transport.handlers 'status-im.test.transport.handlers
'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.handlers-macro
'status-im.test.utils.money 'status-im.test.utils.money
'status-im.test.utils.clocks 'status-im.test.utils.clocks
'status-im.test.utils.ethereum.eip681 'status-im.test.utils.ethereum.eip681

View File

@ -7,9 +7,9 @@
(let [cofx {:db {:account/account {:public-key "1"} (let [cofx {:db {:account/account {:public-key "1"}
:semaphores #{}}}] :semaphores #{}}}]
(testing "it adds the discover filter" (testing "it adds the discover filter"
(is (= (:shh/add-discovery-filter (protocol/initialize-protocol "user-address" cofx))))) (is (= (:shh/add-discovery-filter (protocol/initialize-protocol cofx "user-address")))))
(testing "it restores the sym-keys" (testing "it restores the sym-keys"
(is (= (:shh/restore-sym-keys (protocol/initialize-protocol "user-address" cofx))))) (is (= (:shh/restore-sym-keys (protocol/initialize-protocol cofx "user-address")))))
(testing "custom mailservers" (testing "custom mailservers"
(let [ms-1 {:id "1" (let [ms-1 {:id "1"
:fleet :eth.beta :fleet :eth.beta
@ -42,5 +42,5 @@
ms-3])] ms-3])]
(is (= expected-wnodes (is (= expected-wnodes
(get-in (get-in
(protocol/initialize-protocol "user-address" cofx-with-ms) (protocol/initialize-protocol cofx-with-ms "user-address")
[:db :inbox/wnodes]))))))) [:db :inbox/wnodes])))))))

View File

@ -13,10 +13,10 @@
(deftest receive-whisper-messages-test (deftest receive-whisper-messages-test
(testing "an error is reported" (testing "an error is reported"
(is (nil? (handlers/receive-whisper-messages {} [nil "error" #js [] nil])))) (is (nil? (handlers/receive-whisper-messages {:db {}} [nil "error" #js [] nil]))))
(testing "messages is undefined" (testing "messages is undefined"
(is (nil? (handlers/receive-whisper-messages {} [nil nil js/undefined nil])))) (is (nil? (handlers/receive-whisper-messages {:db {}} [nil nil js/undefined nil]))))
(testing "happy path" (testing "happy path"
(let [actual (handlers/receive-whisper-messages {} [nil nil messages "1"])] (let [actual (handlers/receive-whisper-messages {:db {}} [nil nil messages "1"])]
(testing "it add an fx for the message" (testing "it add an fx for the message"
(is (:chat-received-message/add-fx actual)))))) (is (:chat-received-message/add-fx actual))))))

View File

@ -12,34 +12,34 @@
:inbox/wnodes {:eth.beta {"mailserver-a" {:sym-key-id sym-key :inbox/wnodes {:eth.beta {"mailserver-a" {:sym-key-id sym-key
:address "enode://wnode-id@ip"}}}}}) :address "enode://wnode-id@ip"}}}}})
(defn peers-summary-change-fx-result [sym-key registered-peer? registered-peer-before?] (defn peers-summary-change-result [sym-key registered-peer? registered-peer-before?]
(inbox/peers-summary-change-fx (if registered-peer-before? (inbox/peers-summary-change (cofx-fixtures sym-key
[{:id "wnode-id"}] registered-peer?)
[]) (if registered-peer-before?
(cofx-fixtures sym-key [{:id "wnode-id"}]
registered-peer?))) [])))
(deftest peers-summary-change-fx (deftest peers-summary-change
(testing "Mailserver connected" (testing "Mailserver connected"
(let [result (peers-summary-change-fx-result false true false)] (let [result (peers-summary-change-result false true false)]
(is (= (into #{} (keys result)) (is (= (into #{} (keys result))
#{:status-im.transport.inbox/mark-trusted-peer})))) #{:status-im.transport.inbox/mark-trusted-peer}))))
(testing "Mailserver disconnected, sym-key exists" (testing "Mailserver disconnected, sym-key exists"
(let [result (peers-summary-change-fx-result true false true)] (let [result (peers-summary-change-result true false true)]
(is (= (into #{} (keys result)) (is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later})) #{:db :status-im.transport.inbox/add-peer :utils/dispatch-later}))
(is (= (get-in result [:db :mailserver-status]) (is (= (get-in result [:db :mailserver-status])
:connecting)))) :connecting))))
(testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)" (testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)"
(let [result (peers-summary-change-fx-result false false true)] (let [result (peers-summary-change-result false false true)]
(is (= (into #{} (keys result)) (is (= (into #{} (keys result))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password})) #{:db :status-im.transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
(is (= (get-in result [:db :mailserver-status]) (is (= (get-in result [:db :mailserver-status])
:connecting)))) :connecting))))
(testing "Mailserver isn't concerned by peer summary changes" (testing "Mailserver isn't concerned by peer summary changes"
(is (= (into #{} (keys (peers-summary-change-fx-result true true true))) (is (= (into #{} (keys (peers-summary-change-result true true true)))
#{})) #{}))
(is (= (into #{} (keys (peers-summary-change-fx-result true false false))) (is (= (into #{} (keys (peers-summary-change-result true false false)))
#{})))) #{}))))
(deftest connect-to-mailserver (deftest connect-to-mailserver
@ -101,7 +101,7 @@
(get-in actual [::inbox/request-messages 1 :topics]))))))) (get-in actual [::inbox/request-messages 1 :topics])))))))
(testing "inbox is not ready" (testing "inbox is not ready"
(testing "it does not do anything" (testing "it does not do anything"
(is (nil? (inbox/request-messages {}))))))) (is (nil? (inbox/request-messages {:db {}})))))))
(deftest request-messages-params (deftest request-messages-params
(let [mailserver {:address "peer" (let [mailserver {:address "peer"
@ -171,14 +171,14 @@
(testing "it sets it to now in seconds" (testing "it sets it to now in seconds"
(is (= 10 (is (= 10
(get-in (get-in
(inbox/initialize-offline-inbox [] {:now 10000 :db db}) (inbox/initialize-offline-inbox {:now 10000 :db db} [])
[:db :account/account :last-request]))))) [:db :account/account :last-request])))))
(testing "last-request is set" (testing "last-request is set"
(testing "leaves it unchanged" (testing "leaves it unchanged"
(is (= "sometimeago" (is (= "sometimeago"
(get-in (get-in
(inbox/initialize-offline-inbox (inbox/initialize-offline-inbox
[]
{:now "now" {:now "now"
:db (assoc-in db [:account/account :last-request] "sometimeago")}) :db (assoc-in db [:account/account :last-request] "sometimeago")}
[])
[:db :account/account :last-request]))))))) [:db :account/account :last-request])))))))

View File

@ -1,125 +0,0 @@
(ns status-im.test.ui.screens.accounts.recover.models
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.accounts.recover.core :as models]
[clojure.string :as string]
[status-im.utils.security :as security]
[status-im.i18n :as i18n]))
;;;; helpers
(deftest check-password-errors
(is (= :required-field (models/check-password-errors nil)))
(is (= :required-field (models/check-password-errors " ")))
(is (= :required-field (models/check-password-errors " \t\n ")))
(is (= :recover-password-too-short) (models/check-password-errors "a"))
(is (= :recover-password-too-short) (models/check-password-errors "abc"))
(is (= :recover-password-too-short) (models/check-password-errors "12345"))
(is (nil? (models/check-password-errors "123456")))
(is (nil? (models/check-password-errors "thisisapasswoord"))))
(deftest check-phrase-errors
(is (= :required-field (models/check-phrase-errors nil)))
(is (= :required-field (models/check-phrase-errors " ")))
(is (= :required-field (models/check-phrase-errors " \t\n ")))
(is (= :recovery-phrase-invalid (models/check-phrase-errors "phrase with four words")))
(is (= :recovery-phrase-invalid (models/check-phrase-errors "phrase with five cool words")))
(is (nil? (models/check-phrase-errors "monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey")))
(is (nil? (models/check-phrase-errors (string/join " " (repeat 15 "monkey")))))
(is (nil? (models/check-phrase-errors (string/join " " (repeat 18 "monkey")))))
(is (nil? (models/check-phrase-errors (string/join " " (repeat 24 "monkey")))))
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 14 "monkey")))))
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 11 "monkey")))))
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 19 "monkey")))))
(is (= :recovery-phrase-invalid (models/check-phrase-errors "monkey monkey monkey 12345 monkey adf+123 monkey monkey monkey monkey monkey monkey")))
;;NOTE(goranjovic): the following check should be ok because we sanitize extra whitespace
(is (nil? (models/check-phrase-errors " monkey monkey monkey\t monkey monkey monkey monkey monkey monkey monkey monkey monkey \t "))))
(deftest check-phrase-warnings
(is (nil? (models/check-phrase-warnings "monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey")))
(is (nil? (models/check-phrase-warnings "game buzz method pretty olympic fat quit display velvet unveil marine crater")))
(is (= :recovery-phrase-unknown-words (models/check-phrase-warnings "game buzz method pretty zeus fat quit display velvet unveil marine crater"))))
;;;; handlers
(deftest set-phrase
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:passphrase-valid? true}}}
(models/set-phrase (security/mask-data "game buzz method pretty olympic fat quit display velvet unveil marine crater") {:db {}})))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:passphrase-valid? true}}}
(models/set-phrase (security/mask-data "Game buzz method pretty Olympic fat quit DISPLAY velvet unveil marine crater") {:db {}})))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
:passphrase-valid? true}}}
(models/set-phrase (security/mask-data "game buzz method pretty zeus fat quit display velvet unveil marine crater") {:db {}})))
(is (= {:db {:accounts/recover {:passphrase " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "
:passphrase-valid? true}}}
(models/set-phrase (security/mask-data " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater ") {:db {}})))
(is (= {:db {:accounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"
:passphrase-valid? false}}}
(models/set-phrase (security/mask-data "game buzz method pretty 1234 fat quit display velvet unveil marine crater") {:db {}}))))
(deftest validate-phrase
(is (= {:db {:accounts/recover {:passphrase-error nil
:passphrase-warning nil
:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"}}}
(models/validate-phrase {:db {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"}}})))
(is (= {:db {:accounts/recover {:passphrase-error nil
:passphrase-warning :recovery-phrase-unknown-words
:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"}}}
(models/validate-phrase {:db {:accounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"}}})))
(is (= {:db {:accounts/recover {:passphrase-error :recovery-phrase-invalid
:passphrase-warning :recovery-phrase-unknown-words
:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"}}}
(models/validate-phrase {:db {:accounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"}}}))))
(deftest set-password
(is (= {:db {:accounts/recover {:password " "
:password-valid? false}}}
(models/set-password (security/mask-data " ") {:db {}})))
(is (= {:db {:accounts/recover {:password "abc"
:password-valid? false}}}
(models/set-password (security/mask-data "abc") {:db {}})))
(is (= {:db {:accounts/recover {:password "thisisapaswoord"
:password-valid? true}}}
(models/set-password (security/mask-data "thisisapaswoord") {:db {}}))))
(deftest validate-password
(is (= {:db {:accounts/recover {:password " "
:password-error :required-field}}}
(models/validate-password {:db {:accounts/recover {:password " "}}})))
(is (= {:db {:accounts/recover {:password "abc"
:password-error :recover-password-too-short}}}
(models/validate-password {:db {:accounts/recover {:password "abc"}}})))
(is (= {:db {:accounts/recover {:password "thisisapaswoord"
:password-error nil}}}
(models/validate-password {:db {:accounts/recover {:password "thisisapaswoord"}}}))))
(deftest recover-account
(let [new-cofx (models/recover-account {:db {:accounts/recover
{:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
:password "thisisapaswoord"}}})]
(is (= {:accounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
:password "thisisapaswoord"
:processing? true}}
(:db new-cofx)))
(is (= security/MaskedData
(-> new-cofx :recover-account-fx first type)))
(is (= "thisisapaswoord" (-> new-cofx :recover-account-fx second)))))
(deftest recover-account-with-checks
(let [new-cofx (models/recover-account-with-checks {:db {:accounts/recover
{:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:password "thisisapaswoord"}}})]
(is (= {:accounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
:password "thisisapaswoord"
:processing? true}}
(:db new-cofx)))
(is (= security/MaskedData
(-> new-cofx :recover-account-fx first type)))
(is (= "thisisapaswoord" (-> new-cofx :recover-account-fx second))))
(let [new-cofx (models/recover-account-with-checks {:db {:accounts/recover
{:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
:password "thisisapaswoord"}}})]
(is (= (i18n/label :recovery-typo-dialog-title) (-> new-cofx :ui/show-confirmation :title)))
(is (= (i18n/label :recovery-typo-dialog-description) (-> new-cofx :ui/show-confirmation :content)))
(is (= (i18n/label :recovery-confirm-phrase) (-> new-cofx :ui/show-confirmation :confirm-button-text)))))

View File

@ -7,12 +7,12 @@
(deftest test-handle-qr-code (deftest test-handle-qr-code
(testing "handle contact code" (testing "handle contact code"
(is (= :profile (is (= :profile
(get-in (models/handle-qr-code "0x04405dfcf94380f9159a1bf8d7dbfce19dd2a3552695bf5e6dd96fb8c3c016c62adaf036b387e7f68621c366186f59dae2561374752996aa13ffc57aad9e6e7202" cofx) [:db :view-id])))) (get-in (models/handle-qr-code cofx "0x04405dfcf94380f9159a1bf8d7dbfce19dd2a3552695bf5e6dd96fb8c3c016c62adaf036b387e7f68621c366186f59dae2561374752996aa13ffc57aad9e6e7202") [:db :view-id]))))
(testing "handle own contact code" (testing "handle own contact code"
(is (= :my-profile (is (= :my-profile
(get-in (models/handle-qr-code "0x04e1433c1a8ad71280e6d4b1814aa3958ba6eb451da47ea1d4a4bfc4a04969c445548f3bd9d40fa7e4356aa62075b4d7615179ef1332f1d6a7c59b96c4ab8e04c1" cofx) [:db :view-id])))) (get-in (models/handle-qr-code cofx "0x04e1433c1a8ad71280e6d4b1814aa3958ba6eb451da47ea1d4a4bfc4a04969c445548f3bd9d40fa7e4356aa62075b4d7615179ef1332f1d6a7c59b96c4ab8e04c1") [:db :view-id]))))
(testing "handle universal link" (testing "handle universal link"
(is (= (:browser/show-browser-selection (models/handle-qr-code "status-im://browse/www.cryptokitties.co" cofx)) (is (= (:browser/show-browser-selection (models/handle-qr-code cofx "status-im://browse/www.cryptokitties.co"))
"status-im://browse/www.cryptokitties.co"))) "status-im://browse/www.cryptokitties.co")))
(testing "handle invalid qr code" (testing "handle invalid qr code"
(is (:utils/show-popup (models/handle-qr-code "a random string" cofx))))) (is (:utils/show-popup (models/handle-qr-code cofx "a random string")))))

View File

@ -10,8 +10,8 @@
(is (= :aud (subs/get-currency {:account/account {:settings {:wallet {:currency :aud}}}})))) (is (= :aud (subs/get-currency {:account/account {:settings {:wallet {:currency :aud}}}}))))
(deftest set-currency (deftest set-currency
(let [cofx (models/set-currency :usd {:db {:account/account {:settings {:wallet {}}}}})] (let [cofx (models/set-currency {:db {:account/account {:settings {:wallet {}}}}} :usd)]
(is (= [:db :get-balance :get-tokens-balance :get-prices :data-store/base-tx] (keys cofx))) (is (= [:db :get-balance :get-tokens-balance :get-prices :data-store/base-tx] (keys cofx)))
(is (= :usd (get-in cofx [:db :account/account :settings :wallet :currency])))) (is (= :usd (get-in cofx [:db :account/account :settings :wallet :currency]))))
(is (= :jpy (get-in (models/set-currency :jpy {:db {:account/account {:settings {:wallet {}}}}}) (is (= :jpy (get-in (models/set-currency {:db {:account/account {:settings {:wallet {}}}}} :jpy)
[:db :account/account :settings :wallet :currency])))) [:db :account/account :settings :wallet :currency]))))

View File

@ -1,32 +0,0 @@
(ns status-im.test.utils.handlers-macro
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.utils.handlers-macro :as m]))
(deftest merge-fx
(letfn [(add-b [cofx]
(assoc-in cofx [:db :b] "b"))
(add-c [cofx]
(assoc-in cofx [:db :c] "c"))
(add-tx [tx cofx]
(assoc cofx :data-store/tx [tx]))]
(testing "it updates db correctly"
(let [actual (m/merge-fx {:db {:a "a"}}
(add-b)
(add-c))]
(is (= {:db {:a "a"
:b "b"
:c "c"}} actual))))
(testing "it updates db correctly when a fn don't update it"
(let [empty-fn (constantly nil)
actual (m/merge-fx {:db {:a "a"}}
(add-b)
(empty-fn)
(add-c))]
(is (= {:db {:a "a"
:b "b"
:c "c"}} actual))))
#_(testing "it updates data-store/tx correctly"
(let [actual (m/merge-fx {:data-store/tx [1]}
(add-tx 2)
(add-tx 3))]
(is (= {:data-store/tx [1 2 3]} actual))))))

View File

@ -7,39 +7,33 @@
(testing "the user is not logged in" (testing "the user is not logged in"
(testing "it stores the url for later processing" (testing "it stores the url for later processing"
(is (= {:db {:universal-links/url "some-url"}} (is (= {:db {:universal-links/url "some-url"}}
(links/handle-url "some-url" {:db {}}))))) (links/handle-url {:db {}} "some-url")))))
(testing "the user is logged in" (testing "the user is logged in"
(let [db {:account/account {:public-key "pk"} (let [db {:account/account {:public-key "pk"}
:universal-links/url "some-url"}] :universal-links/url "some-url"}]
(testing "it clears the url" (testing "it clears the url"
(is (nil? (get-in (links/handle-url "some-url" (is (nil? (get-in (links/handle-url {:db db} "some-url")
{:db db})
[:db :universal-links/url])))) [:db :universal-links/url]))))
(testing "a public chat link" (testing "a public chat link"
(testing "it joins the chat" (testing "it joins the chat"
(is (get-in (links/handle-url "status-im://chat/public/status" (is (get-in (links/handle-url {:db db} "status-im://chat/public/status")
{:db db})
[:db :chats "status"])))) [:db :chats "status"]))))
(testing "a browse dapp link" (testing "a browse dapp link"
(testing "it open the dapps" (testing "it open the dapps"
(is (is
(= "status-im://browse/www.cryptokitties.co" (= "status-im://browse/www.cryptokitties.co"
(:browser/show-browser-selection (links/handle-url "status-im://browse/www.cryptokitties.co" (:browser/show-browser-selection (links/handle-url {:db db} "status-im://browse/www.cryptokitties.co"))))))
{:db db}))))))
(testing "a user profile link" (testing "a user profile link"
(testing "it loads the profile" (testing "it loads the profile"
(let [actual (links/handle-url "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (let [actual (links/handle-url {:db db} "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")]
{:db db})]
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity])))))) (is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity]))))))
(testing "if does nothing because the link is invalid" (testing "if does nothing because the link is invalid"
(is (= (links/handle-url "status-im://user/CONTACTCODE" (is (= (links/handle-url {:db db} "status-im://user/CONTACTCODE")
{:db db})
nil))) nil)))
(testing "a not found url" (testing "a not found url"
(testing "it does nothing" (testing "it does nothing"
(is (nil? (links/handle-url "status-im://not-existing" (is (nil? (links/handle-url {:db db} "status-im://not-existing"))))))))
{:db db}))))))))
(deftest url-event-listener (deftest url-event-listener
(testing "the url is not nil" (testing "the url is not nil"