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.wallet.settings.models :as wallet.settings.models]
[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]))
shown? (get-in db [:account/account :mainnet-warning-shown?])]
(when (and config/mainnet-warning-enabled?
@ -24,29 +24,31 @@
(not (:in-progress? 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])]
(if modal?
{:dispatch [:navigate-to-clean :wallet-send-transaction-modal]}
(if-not (chat-send? transaction)
(navigation/navigate-to-clean :wallet cofx)
(navigation/navigate-to-cofx :wallet-send-transaction-modal nil cofx)))))
(navigation/navigate-to-clean cofx :wallet nil)
(navigation/navigate-to-cofx cofx :wallet-send-transaction-modal nil)))))
(defn confirm-wallet-set-up [modal? {:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
(continue-after-wallet-onboarding db modal?)
(wallet.settings.models/wallet-autoconfig-tokens)
(accounts.update/account-update {:wallet-set-up-passed? true})))
(fx/defn confirm-wallet-set-up
[{:keys [db] :as cofx} modal?]
(fx/merge cofx
(continue-after-wallet-onboarding modal?)
(wallet.settings.models/wallet-autoconfig-tokens)
(accounts.update/account-update {:wallet-set-up-passed? true} {})))
(defn switch-dev-mode [dev-mode? cofx]
(merge (accounts.update/account-update {:dev-mode? dev-mode?} cofx)
(fx/defn switch-dev-mode [cofx dev-mode?]
(merge (accounts.update/account-update cofx
{:dev-mode? dev-mode?}
{})
(if dev-mode?
{:dev-server/start 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])]
(accounts.update/update-settings
(assoc settings :web3-opt-in? opt-in)
cofx)))
(accounts.update/update-settings cofx
(assoc settings :web3-opt-in? opt-in)
{})))

View File

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

View File

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

View File

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

View File

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

View File

@ -2,43 +2,40 @@
(:require [status-im.data-store.accounts :as accounts-store]
[status-im.transport.message.core :as transport]
[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.
Optionally, one can specify a success-event to be dispatched after fields are persisted."
([new-account-fields cofx]
(account-update new-account-fields nil cofx))
([new-account-fields success-event {:keys [db] :as cofx}]
(let [current-account (:account/account db)
new-account (merge current-account new-account-fields)
fcm-token (get-in db [:notifications :fcm-token])
fx {:db (assoc db :account/account new-account)
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
:success-event success-event}]}
{:keys [name photo-path address]} new-account]
(if (or (:name new-account-fields) (:photo-path new-account-fields))
(handlers-macro/merge-fx
cofx
fx
(transport/send (message.contact/ContactUpdate. name photo-path address fcm-token) nil))
fx))))
[{:keys [db] :as cofx} new-account-fields {:keys [success-event]}]
(let [current-account (:account/account db)
new-account (merge current-account new-account-fields)
fcm-token (get-in db [:notifications :fcm-token])
fx {:db (assoc db :account/account new-account)
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
:success-event success-event}]}
{:keys [name photo-path address]} new-account]
(if (or (:name new-account-fields) (:photo-path new-account-fields))
(fx/merge cofx
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."
[cofx]
(account-update {:seed-backed-up? true
(account-update cofx
{:seed-backed-up? true
:mnemonic nil}
cofx))
{}))
(defn update-sign-in-time
(fx/defn update-sign-in-time
[{db :db now :now :as cofx}]
(account-update {:last-sign-in now} cofx))
(account-update cofx {:last-sign-in now} {}))
(defn update-settings
([settings cofx] (update-settings settings nil cofx))
([settings success-event {{:keys [account/account] :as db} :db :as cofx}]
(let [new-account (assoc account :settings settings)]
{:db (assoc db :account/account new-account)
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
:success-event success-event}]})))
(fx/defn update-settings
[{{:keys [account/account] :as db} :db :as cofx} settings {:keys [success-event]}]
(let [new-account (assoc account :settings settings)]
{:db (assoc db :account/account new-account)
:data-store/base-tx [{:transaction (accounts-store/save-account-tx new-account)
:success-event success-event}]}))

View File

@ -4,7 +4,7 @@
[status-im.accounts.update.core :as accounts.update]
[status-im.i18n :as i18n]
[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})")
@ -17,11 +17,12 @@
:id (string/replace id "-" "")
:name bootnode-name})
(defn fetch [id cofx]
(fx/defn fetch [cofx id]
(let [network (get-in cofx [:db :network])]
(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
:bootnodes/manage
@ -33,32 +34,32 @@
:name (string/blank? value)
:url (not (valid-address? value)))})})
(defn edit [id {:keys [db] :as cofx}]
(fx/defn edit
[{:keys [db] :as cofx} id]
(let [{:keys [id
address
name]} (fetch id cofx)
fxs (handlers-macro/merge-fx
cofx
(set-input :id id)
(set-input :url (str address))
(set-input :name (str name)))]
name]} (fetch cofx id)
fxs (fx/merge cofx
(set-input :id id)
(set-input :url (str address))
(set-input :name (str name)))]
(assoc fxs :dispatch [:navigate-to :edit-bootnode])))
(defn custom-bootnodes-in-use? [{:keys [db] :as cofx}]
(let [network (:network db)]
(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)
new-account (update-in account [:bootnodes network] dissoc id)]
(handlers-macro/merge-fx cofx
{:db (assoc db :account/account new-account)}
(accounts.update/account-update
(select-keys new-account [:bootnodes])
(when (custom-bootnodes-in-use? cofx)
[:accounts.update.callback/save-settings-success])))))
(fx/merge cofx
{:db (assoc db :account/account new-account)}
(accounts.update/account-update
(select-keys new-account [:bootnodes])
{:success-event (when (custom-bootnodes-in-use? cofx)
[: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
id
url]} manage
@ -73,34 +74,36 @@
[network (:id bootnode)]
bootnode)]
(handlers-macro/merge-fx
cofx
{:db (dissoc db :bootnodes/manage)
:dispatch [:navigate-back]}
(accounts.update/account-update
{:bootnodes new-bootnodes}
(when (custom-bootnodes-in-use? cofx)
[:accounts.update.callback/save-settings-success])))))
(fx/merge cofx
{:db (dissoc db :bootnodes/manage)
:dispatch [:navigate-back]}
(accounts.update/account-update
{:bootnodes new-bootnodes}
{:success-event (when (custom-bootnodes-in-use? cofx)
[: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])
settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx
(accounts.update/update-settings
(assoc-in settings [:bootnodes network] value)
[:accounts.update.callback/save-settings-success]))))
(accounts.update/update-settings cofx
(assoc-in settings [:bootnodes network] value)
{:success-event [: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)
: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)
:content (i18n/label :t/delete-bootnode-are-you-sure)
:confirm-button-text (i18n/label :t/delete-bootnode)
:on-accept #(re-frame/dispatch [:bootnodes.ui/delete-confirmed bootnode-id])}})
(defn delete-bootnode [bootnode-id cofx]
(handlers-macro/merge-fx cofx
(delete bootnode-id)
(navigation/navigate-back)))
(fx/defn delete-bootnode
[cofx bootnode-id]
(fx/merge cofx
(delete bootnode-id)
(navigation/navigate-back)))

View File

@ -14,7 +14,7 @@
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.ens :as ens]
[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.multihash :as multihash]
[status-im.utils.platform :as platform]
@ -23,12 +23,12 @@
[status-im.utils.universal-links.core :as utils.universal-links]
[taoensso.timbre :as log]))
(defn initialize-browsers
(fx/defn initialize-browsers
[{:keys [db all-stored-browsers]}]
(let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))]
{:db (assoc db :browser/browsers browsers)}))
(defn initialize-dapp-permissions
(fx/defn initialize-dapp-permissions
[{:keys [db all-dapp-permissions]}]
(let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))]
{:db (assoc db :dapps/permissions dapp-permissions)}))
@ -42,7 +42,8 @@
(and (not error?)
(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)
: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 _)))]
(assoc browser :unsafe? (dependencies/phishing-detect history-host))))
(defn update-browser
[{:keys [browser-id history history-index error? dapp?] :as browser}
{:keys [db now]}]
(fx/defn update-browser
[{:keys [db now]}
{:keys [browser-id history history-index error? dapp?] :as browser}]
(let [updated-browser (-> (assoc browser :timestamp now)
(check-if-dapp-in-list)
(check-if-phishing-url))]
@ -77,24 +78,24 @@
(defn can-go-back? [{:keys [history-index]}]
(pos? history-index))
(defn navigate-to-previous-page
(fx/defn navigate-to-previous-page
[cofx]
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
(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]}]
(< history-index (dec (count history))))
(defn navigate-to-next-page
(fx/defn navigate-to-next-page
[cofx]
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
(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
[browser url loading? cofx]
[cofx browser url loading?]
(when-not loading?
(let [history-index (:history-index browser)
history (:history browser)
@ -107,10 +108,10 @@
new-index (if slash?
history-index
(dec (count new-history)))]
(update-browser (assoc browser
(update-browser cofx
(assoc browser
:history new-history
:history-index new-index)
cofx))))))
:history-index new-index)))))))
(defn ens? [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-error]))))
(defn resolve-ens-multihash-success
[hash {:keys [db] :as cofx}]
(fx/defn resolve-ens-multihash-success
[{:keys [db] :as cofx} hash]
(let [options (:browser/options db)
browsers (:browser/browsers db)
browser (get browsers (:browser-id options))
history-index (:history-index browser)]
(handlers-macro/merge-fx
cofx
{:db (assoc-in db [:browser/options :resolving?] false)}
(update-browser (assoc-in browser [:history history-index]
(str "https://ipfs.infura.io/ipfs/" hash))))))
(fx/merge cofx
{:db (assoc-in db [:browser/options :resolving?] false)}
(update-browser (assoc-in browser [:history history-index]
(str "https://ipfs.infura.io/ipfs/" hash))))))
(defn resolve-ens-multihash
[host loading? error? {{:keys [web3 network] :as db} :db}]
(fx/defn resolve-ens-multihash
[{{:keys [web3 network] :as db} :db} host loading? error?]
(when (and (not loading?)
(not error?)
(ens? host))
@ -148,86 +148,82 @@
:ens-name host
:cb resolve-ens-multihash-callback}})))
(defn update-browser-option
[option-key option-value {:keys [db]}]
(fx/defn update-browser-option
[{:keys [db]} option-key option-value]
{:db (assoc-in db [:browser/options option-key] option-value)})
(defn handle-browser-error [cofx]
(handlers-macro/merge-fx cofx
(update-browser-option :error? true)
(update-browser-option :loading? false)))
(fx/defn handle-browser-error
[cofx]
(fx/merge cofx
(update-browser-option :error? true)
(update-browser-option :loading? false)))
(defn update-browser-loading-option
[loading? cofx]
;; 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]
(fx/defn update-browser-on-nav-change
[cofx browser url loading? error?]
(when (not= "about:blank" url)
(let [host (http/url-host url)]
(handlers-macro/merge-fx cofx
(resolve-ens-multihash host loading? error?)
(update-browser-history browser url loading?)))))
(fx/merge cofx
(resolve-ens-multihash host loading? error?)
(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))
{:strs [url loading]} (js->clj event)]
(handlers-macro/merge-fx cofx
(update-browser-loading-option loading)
(update-browser-on-nav-change browser url loading error?))))
(fx/merge cofx
#(when platform/ios?
(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
and history of the current browser is updated so that the user can navigate back to the
origin url"
;; TODO(yenda) is that desirable ?
[url cofx]
[cofx url]
(let [browser (get-current-browser (:db cofx))
normalized-url (http/normalize-and-decode-url url)
host (http/url-host normalized-url)]
(handlers-macro/merge-fx cofx
(update-browser-option :url-editing? false)
(resolve-ens-multihash host false false)
(update-browser-history browser normalized-url false))))
(fx/merge cofx
(update-browser-option :url-editing? false)
(resolve-ens-multihash host false false)
(update-browser-history browser normalized-url false))))
(defn navigate-to-browser
(fx/defn navigate-to-browser
[{{:keys [view-id]} :db :as cofx}]
(if (= view-id :dapp-description)
(navigation/navigate-reset
{:index 1
:actions [{:routeName :home}
{:routeName :browser}]}
cofx)
(navigation/navigate-to-cofx :browser nil cofx)))
(navigation/navigate-reset cofx
{:index 1
:actions [{:routeName :home}
{:routeName :browser}]})
(navigation/navigate-to-cofx cofx :browser nil)))
(defn open-url
(fx/defn open-url
"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
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)
host (http/url-host normalized-url)
browser {:browser-id (or host (random/id))
:history-index 0
:history [normalized-url]}]
(handlers-macro/merge-fx cofx
{:db (assoc db :browser/options
{:browser-id (:browser-id browser)})}
(navigate-to-browser)
(update-browser browser)
(resolve-ens-multihash host false false))))
(fx/merge cofx
{:db (assoc db :browser/options
{:browser-id (:browser-id browser)})}
(navigate-to-browser)
(update-browser browser)
(resolve-ens-multihash host false false))))
(defn open-existing-browser
(fx/defn open-existing-browser
"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])]
(handlers-macro/merge-fx cofx
{:db (assoc db :browser/options
{:browser-id browser-id})}
(update-browser browser)
(navigation/navigate-to-cofx :browser nil))))
(fx/merge cofx
{:db (assoc db :browser/options
{:browser-id browser-id})}
(update-browser browser)
(navigation/navigate-to-cofx :browser nil))))
(defn web3-send-async
[{:keys [method] :as payload} message-id {:keys [db]}]
@ -243,7 +239,8 @@
:error %1
:result %2}])]}))
(defn send-to-bridge [message cofx]
(fx/defn send-to-bridge
[cofx message]
{:browser/send-to-bridge {:message message
:webview (get-in cofx [:db :webview-bridge])}})
@ -259,14 +256,14 @@
cofx)
(web3-send-async payload message-id cofx))))
(defn handle-scanned-qr-code
[data message cofx]
(handlers-macro/merge-fx cofx
(send-to-bridge (assoc message :result data))
(navigation/navigate-back)))
(fx/defn handle-scanned-qr-code
[cofx data message]
(fx/merge cofx
(send-to-bridge (assoc message :result data))
(navigation/navigate-back)))
(defn process-bridge-message
[message {:keys [db] :as cofx}]
(fx/defn process-bridge-message
[{:keys [db] :as cofx} message]
(let [{:browser/keys [options browsers]} db
{:keys [browser-id]} options
browser (get browsers browser-id)
@ -287,18 +284,19 @@
(web3-send-async-read-only dapp-name payload messageId cofx)
(= 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}
{:type constants/scan-qr-code-callback
:data data})
cofx)
:data data}))
(= 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)
(utils.universal-links/handle-url link cofx)
(utils.universal-links/handle-url cofx link)
{:browser/show-browser-selection link}))
(defn filter-letters-numbers-and-replace-dot-on-dash [value]
@ -310,7 +308,8 @@
(= 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)))]
{:dispatch [:create-new-public-chat topic true]}))

View File

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

View File

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

View File

@ -3,7 +3,8 @@
[status-im.chat.commands.core :as commands]
[status-im.chat.constants :as chat-constants]
[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]
(when selection
@ -25,10 +26,10 @@
(> input-params-count params-count) :more-than-needed)))
(defn selected-chat-command
"Takes input text, text-selection and `protocol/id->command-props` map (result of
the `chat-commands` fn) and returns the corresponding `command-props` entry,
"Takes input text, text-selection and `protocol/id->command-props` map (result of
the `chat-commands` fn) and returns the corresponding `command-props` entry,
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`
# `: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
@ -50,9 +51,9 @@
:current-param-position (current-param-position input-text text-selection)
: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"
[last-param? param-index value {:keys [db]}]
[{:keys [db]} last-param? param-index value]
(let [{:keys [current-chat-id chats]} db
[command & params] (-> (get-in chats [current-chat-id :input-text])
input-model/split-command-args)
@ -73,9 +74,9 @@
(chat-model/set-chat-ui-props {:validation-messages nil})
(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"
[{:keys [type params]} input-params {:keys [db]}]
[{:keys [db]} {:keys [type params]} input-params]
(let [{:keys [current-chat-id chat-ui-props]} db]
{:db (-> db
(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
where in which command is available, together with `id` it forms unique
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
`:personal-chats` - command is available for any personal 1-1 chat
`:group-chats` - command is available for any group chat
`:public-chats` - command is available for any public chat ")
(description [this] "Description of the command")
(parameters [this]
"Ordered sequence of command parameter templates, where each parameter
is defined as map consisting of mandatory `:id`, `:title` and `:type` keys,
"Ordered sequence of command parameter templates, where each parameter
is defined as map consisting of mandatory `:id`, `:title` and `:type` keys,
and optional `:suggestions` field.
When used, `:suggestions` containes reference to any generic helper component
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.
Each error is represented by the map containing `:title` and `:description` keys.")
(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")
(on-receive [this command-message cofx]
"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
(: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
;; with old command references will be low
@ -16,10 +17,10 @@
(or (get id->command path)
(get id->command (get old->new-path path)))))
(defn receive
(fx/defn receive
"Performs receive effects for command message. Does nothing
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)]
(when-let [{:keys [type]} (lookup-command-by-ref message id->command)]
(protocol/on-receive type message cofx))))

View File

@ -6,7 +6,7 @@
[status-im.chat.models :as chat-model]
[status-im.chat.models.input :as input-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
;; with old command references will be low
@ -43,9 +43,9 @@
:params (or new-parameter-map parameter-map)}
content)}))
(defn validate-and-send
(fx/defn validate-and-send
"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)
parameter-map (commands-input/parse-parameters params input-text)]
(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
:sending-in-progress? false})}
;; no errors, define clean-up effects which will have to be performed in all cases
(let [cleanup-fx (handlers-macro/merge-fx cofx
{:db (chat-model/set-chat-ui-props
db {:sending-in-progress? false})}
(input-model/set-chat-input-text nil))]
(let [cleanup-fx (fx/merge cofx
{:db (chat-model/set-chat-ui-props
db {:sending-in-progress? false})}
(input-model/set-chat-input-text nil))]
(if (satisfies? protocol/Yielding type)
;; yield control implemented, don't send the message
(handlers-macro/merge-fx cofx
cleanup-fx
(protocol/yield-control type parameter-map))
(fx/merge cofx
cleanup-fx
#(protocol/yield-control type parameter-map %))
;; no yield control, proceed with sending the command message
(let [command-message (create-command-message chat-id type parameter-map cofx)]
(handlers-macro/merge-fx cofx
cleanup-fx
(protocol/on-send type command-message)
(input-model/set-chat-input-metadata nil)
(message-model/send-message command-message))))))))
(fx/merge cofx
cleanup-fx
#(protocol/on-send type command-message %)
(input-model/set-chat-input-metadata nil)
(message-model/send-message command-message))))))))
(defn send
(fx/defn send
"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)]
(handlers-macro/merge-fx cofx
(protocol/on-send type command-message)
(input-model/set-chat-input-metadata nil)
(message-model/send-message command-message))))
(fx/merge cofx
#(protocol/on-send type command-message %)
(input-model/set-chat-input-metadata nil)
(message-model/send-message command-message))))

View File

@ -1,25 +1,25 @@
(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
(defn receive-seen
[chat-id sender {:keys [message-ids]} {:keys [db js-obj]}]
(merge
{:confirm-messages-processed [{:web3 (:web3 db)
:js-obj js-obj}]}
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(select-keys message-ids)
keys)]
(let [statuses (map (fn [message-id]
{:chat-id chat-id
:message-id message-id
:whisper-identity sender
:status :seen})
seen-messages-ids)]
{:db (reduce (fn [acc {:keys [message-id] :as status}]
(assoc-in acc [:chats chat-id :message-statuses
message-id sender]
status))
db
statuses)
:data-store/tx [(user-statuses-store/save-statuses-tx statuses)]}))))
(fx/defn receive-seen
[{:keys [db js-obj]} chat-id sender {:keys [message-ids]}]
(merge {:confirm-messages-processed [{:web3 (:web3 db)
:js-obj js-obj}]}
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(select-keys message-ids)
keys)]
(let [statuses (map (fn [message-id]
{:chat-id chat-id
:message-id message-id
:whisper-identity sender
:status :seen})
seen-messages-ids)]
{:db (reduce (fn [acc {:keys [message-id] :as status}]
(assoc-in acc [:chats chat-id :message-statuses
message-id sender]
status))
db
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.loading :as chat-loading]
[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.i18n :as i18n]
[status-im.transport.message.core :as transport.message]
[status-im.transport.message.v1.group-chat :as group-chat]
[status-im.transport.message.v1.public-chat :as public-chat]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.utils :as utils]))
;;;; Effects
@ -67,7 +66,7 @@
(handlers/register-handler-fx
:navigate-to-chat
(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
:load-more-messages
@ -82,9 +81,9 @@
(models/start-chat contact-id opts cofx)))
(defn remove-chat-and-navigate-home [cofx [_ chat-id]]
(handlers-macro/merge-fx cofx
(models/remove-chat chat-id)
(navigation/replace-view :home)))
(fx/merge cofx
(models/remove-chat chat-id)
(navigation/replace-view :home)))
(handlers/register-handler-fx
:remove-chat-and-navigate-home
@ -111,17 +110,17 @@
:confirm-button-text (i18n/label :t/clear)
:on-accept #(re-frame/dispatch [:clear-history])}}))
(defn create-new-public-chat [topic modal? cofx]
(handlers-macro/merge-fx cofx
(models/add-public-chat topic)
(models/navigate-to-chat topic {:modal? modal?
:navigation-replace? true})
(public-chat/join-public-chat topic)))
(fx/defn create-new-public-chat [cofx topic modal?]
(fx/merge cofx
(models/add-public-chat topic)
(models/navigate-to-chat topic {:modal? modal?
:navigation-replace? true})
(public-chat/join-public-chat topic)))
(handlers/register-handler-fx
:create-new-public-chat
(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]
(->> selected-contacts
@ -139,31 +138,30 @@
(group-name-from-contacts selected-contacts
(:contacts/contacts db)
(:username db)))]
(handlers-macro/merge-fx
cofx
{:db (assoc db :group/selected-contacts #{})}
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
(navigation/navigate-to-cofx :home nil)
(models/navigate-to-chat random-id {})
(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
(fx/merge cofx
{:db (assoc db :group/selected-contacts #{})}
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
(navigation/navigate-to-cofx :home nil)
(models/navigate-to-chat random-id {})
#(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id %)))))
(defn show-profile [identity {:keys [db]}]
(navigation/navigate-to-cofx :profile nil {:db (assoc db :contacts/identity identity)}))
(fx/defn show-profile [{:keys [db]} identity]
(navigation/navigate-to-cofx {:db (assoc db :contacts/identity identity)} :profile nil))
(handlers/register-handler-fx
:show-profile
(fn [cofx [_ identity]]
(show-profile identity cofx)))
(show-profile cofx identity)))
(handlers/register-handler-fx
:resend-message
(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
:delete-message
(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
:disable-cooldown

View File

@ -12,7 +12,7 @@
[status-im.chat.commands.sending :as commands-sending]
[status-im.ui.components.react :as react-comp]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]))
[status-im.utils.fx :as fx]))
;;;; Effects
@ -44,9 +44,9 @@
;;;; Helper functions
(defn chat-input-focus
(fx/defn chat-input-focus
"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])]
{::focus-rn-component cmp-ref}))
@ -55,25 +55,25 @@
(handlers/register-handler-fx
:set-chat-input-text
(fn [cofx [_ text]]
(input-model/set-chat-input-text text cofx)))
(input-model/set-chat-input-text cofx text)))
(handlers/register-handler-fx
:select-chat-input-command
(fn [{:keys [db] :as cofx} [_ command params metadata]]
(handlers-macro/merge-fx cofx
(input-model/set-chat-input-metadata metadata)
(commands-input/select-chat-input-command command params)
(chat-input-focus :input-ref))))
(fx/merge cofx
(input-model/set-chat-input-metadata metadata)
(commands-input/select-chat-input-command command params)
(chat-input-focus :input-ref))))
(handlers/register-handler-fx
:set-command-parameter
(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
:chat-input-focus
(fn [cofx [_ ref]]
(chat-input-focus ref cofx)))
(chat-input-focus cofx ref)))
(handlers/register-handler-fx
:chat-input-blur
@ -84,10 +84,9 @@
(defn command-complete-fx
"command is complete, set `:sending-in-progress?` flag and proceed with command processing"
[input-text command {:keys [db now random-id] :as cofx}]
(handlers-macro/merge-fx
cofx
{:db (model/set-chat-ui-props db {:sending-in-progress? true})}
(commands-sending/validate-and-send input-text command)))
(fx/merge cofx
{:db (model/set-chat-ui-props db {:sending-in-progress? true})}
(commands-sending/validate-and-send input-text command)))
(defn command-not-complete-fx
"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"
[input-text current-chat-id {:keys [db] :as cofx}]
(when-not (string/blank? input-text)
(handlers-macro/merge-fx
cofx
(input-model/set-chat-input-text nil)
(input-model/set-chat-input-metadata nil)
(message-model/send-message {:chat-id current-chat-id
:content-type constants/text-content-type
:content input-text}))))
(fx/merge cofx
(input-model/set-chat-input-text nil)
(input-model/set-chat-input-metadata nil)
(message-model/send-message {:chat-id current-chat-id
:content-type constants/text-content-type
:content input-text}))))
(handlers/register-handler-fx
:send-current-message

View File

@ -3,7 +3,6 @@
[taoensso.timbre :as log]
[status-im.chat.models.message :as message-model]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.models.transactions :as wallet.transactions]))
;;;; Handlers
@ -13,7 +12,7 @@
(fn [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}
{:keys [message-id] :as message}]
(if (and (message-model/add-to-chat? cofx message)
@ -30,4 +29,4 @@
:chat-received-message/add
message-model/receive-interceptors
(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.datetime :as time]
[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]))
(defn group-chat? [chat-id cofx]
(and (multi-user-chat? chat-id cofx)
(defn group-chat? [cofx chat-id]
(and (multi-user-chat? cofx chat-id)
(not (get-in cofx [:db :chats chat-id :public?]))))
(defn public-chat? [chat-id cofx]
@ -45,9 +45,9 @@
:contacts [chat-id]
:last-clock-value 0}))
(defn upsert-chat
(fx/defn upsert-chat
"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
(or (get (:chats db) chat-id)
(create-new-chat chat-id cofx))
@ -59,29 +59,31 @@
;; when chat is deleted, don't change anything
{:db db})))
(defn add-public-chat
(fx/defn add-public-chat
"Adds new public group chat to db & realm"
[topic cofx]
(upsert-chat {:chat-id topic
[cofx topic]
(upsert-chat cofx
{:chat-id topic
:is-active true
:name topic
:group-chat true
:contacts []
:public? true} cofx))
:public? true}))
(defn add-group-chat
(fx/defn add-group-chat
"Adds new private group chat to db & realm"
[chat-id chat-name admin participants cofx]
(upsert-chat {:chat-id chat-id
[cofx chat-id chat-name admin participants]
(upsert-chat cofx
{:chat-id chat-id
:name chat-name
:is-active true
:group-chat true
:group-admin admin
:contacts participants} cofx))
:contacts participants}))
(defn clear-history
(fx/defn clear-history
"Clears history of the particular chat"
[chat-id {:keys [db] :as cofx}]
[{:keys [db] :as cofx} chat-id]
(let [{:keys [messages
deleted-at-clock-value]} (get-in db [:chats chat-id])
last-message-clock-value (or (->> messages
@ -100,13 +102,15 @@
:data-store/tx [(chats-store/clear-history-tx chat-id last-message-clock-value)
(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 (group-chat? chat-id cofx)
(if (group-chat? cofx chat-id)
(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
(assoc-in [:chats chat-id :is-active] false)
(assoc-in [:current-chat-id] nil))
@ -118,26 +122,24 @@
;; (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)
;; 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"
[chat-id {:keys [db now] :as cofx}]
(letfn [(remove-transport-fx [chat-id cofx]
(when (multi-user-chat? chat-id cofx)
(remove-transport chat-id cofx)))]
(handlers-macro/merge-fx
cofx
(remove-transport-fx chat-id)
(deactivate-chat chat-id)
(clear-history chat-id))))
[{:keys [db now] :as cofx} chat-id]
(fx/merge cofx
#(when (multi-user-chat? % chat-id)
(remove-transport % 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?]))
(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
(defn mark-messages-seen
(fx/defn mark-messages-seen
"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]))]
(let [me (:current-public-key db)
updated-statuses (keep (fn [message-id]
@ -148,56 +150,53 @@
all-unviewed-ids)
loaded-unviewed-ids (map :message-id updated-statuses)]
(when (seq loaded-unviewed-ids)
(handlers-macro/merge-fx
cofx
{:db (-> (reduce (fn [acc {:keys [message-id status]}]
(assoc-in acc [:chats chat-id :message-statuses
message-id me :status]
status))
db
updated-statuses)
(update-in [:chats chat-id :unviewed-messages]
#(apply disj % loaded-unviewed-ids)))
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
(send-messages-seen chat-id loaded-unviewed-ids))))))
(fx/merge cofx
{:db (-> (reduce (fn [acc {:keys [message-id status]}]
(assoc-in acc [:chats chat-id :message-statuses
message-id me :status]
status))
db
updated-statuses)
(update-in [:chats chat-id :unviewed-messages]
#(apply disj % loaded-unviewed-ids)))
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
(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"
[chat-id {:keys [db] :as cofx}]
(handlers-macro/merge-fx cofx
{:db (-> (assoc db :current-chat-id chat-id)
(set-chat-ui-props {:validation-messages nil}))}
(mark-messages-seen chat-id)))
[{:keys [db] :as cofx} chat-id]
(fx/merge cofx
{:db (-> (assoc db :current-chat-id chat-id)
(set-chat-ui-props {:validation-messages nil}))}
(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"
[chat-id {:keys [modal? navigation-replace?]} cofx]
[cofx chat-id {:keys [modal? navigation-replace?]}]
(cond
modal?
(handlers-macro/merge-fx
cofx
(navigation/navigate-to-cofx :chat-modal {})
(preload-chat-data chat-id))
(fx/merge cofx
(navigation/navigate-to-cofx :chat-modal {})
(preload-chat-data chat-id))
navigation-replace?
(handlers-macro/merge-fx cofx
(navigation/navigate-reset {:index 1
:actions [{:routeName :home}
{:routeName :chat}]})
(preload-chat-data chat-id))
(fx/merge cofx
(navigation/navigate-reset {:index 1
:actions [{:routeName :home}
{:routeName :chat}]})
(preload-chat-data chat-id))
:else
(handlers-macro/merge-fx cofx
(navigation/navigate-to-cofx :chat {})
(preload-chat-data chat-id))))
(fx/merge cofx
(navigation/navigate-to-cofx :chat {})
(preload-chat-data chat-id))))
(defn start-chat
(fx/defn start-chat
"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
(when (not= (:current-public-key db) chat-id)
(handlers-macro/merge-fx cofx
(upsert-chat {:chat-id chat-id
:is-active true})
(navigate-to-chat chat-id opts))))
(fx/merge cofx
(upsert-chat {:chat-id chat-id
:is-active true})
(navigate-to-chat chat-id opts))))

View File

@ -7,8 +7,8 @@
[status-im.chat.models :as models.chat]
[status-im.transport.message.core :as message]
[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]
{:removed (set/difference existing-participants-set new-participants-set)
@ -41,37 +41,38 @@
admin-name (or (get-in db [:contacts/contacts group-admin :name])
group-admin)]
(if (removed me) ;; we were removed
(handlers-macro/merge-fx cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(str admin-name " " (i18n/label :t/removed-from-chat))))
(models.chat/upsert-chat {:chat-id chat-id
:removed-from-at now
:is-active false})
(transport.utils/unsubscribe-from-chat chat-id))
(handlers-macro/merge-fx cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(prepare-system-message admin-name
added
removed
(:contacts/contacts db))))
(group/participants-added chat-id added)
(group/participants-removed chat-id removed)))))
(fx/merge cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(str admin-name " " (i18n/label :t/removed-from-chat))))
(models.chat/upsert-chat {:chat-id chat-id
:removed-from-at now
:is-active false})
(transport.utils/unsubscribe-from-chat chat-id))
(fx/merge cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(prepare-system-message admin-name
added
removed
(:contacts/contacts db))))
(group/participants-added chat-id added)
(group/participants-removed chat-id removed)))))
;; first time we hear about chat -> create it if we are among participants
(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)
participant-leaving-name (or (get-in db [:contacts/contacts signature :name])
signature)]
(when (and
(not= signature me)
(get-in db [:chats chat-id])) ;; chat is present
(handlers-macro/merge-fx cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(str participant-leaving-name " " (i18n/label :t/left))))
(group/participants-removed chat-id #{signature})
(transport.group-chat/send-new-group-key nil chat-id)))))
(fx/merge cofx
(models.message/receive
(models.message/system-message chat-id random-id now
(str participant-leaving-name " " (i18n/label :t/left))))
(group/participants-removed chat-id #{signature})
(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.utils.config :as config]
[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 " ")
@ -89,16 +90,16 @@
(str const/arg-wrapping-char arg const/arg-wrapping-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
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})
(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"
[metadata {:keys [db] :as cofx}]
[{:keys [db] :as cofx} metadata]
(let [current-chat-id (:current-chat-id db)]
{:db (assoc-in db [:chats current-chat-id :input-metadata] metadata)}))
@ -114,10 +115,11 @@
:chat/spam-messages-frequency 0
:chat/cooldown-enabled? true)})
(defn process-cooldown [{{:keys [chat/last-outgoing-message-sent-at
chat/cooldowns
chat/spam-messages-frequency
current-chat-id] :as db} :db :as cofx}]
(fx/defn process-cooldown
[{{:keys [chat/last-outgoing-message-sent-at
chat/cooldowns
chat/spam-messages-frequency
current-chat-id] :as db} :db :as cofx}]
(when (chat-model/public-chat? current-chat-id cofx)
(let [spamming-fast? (< (- (datetime/timestamp) last-outgoing-message-sent-at)
(+ const/spam-interval-ms (* 1000 cooldowns)))

View File

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

View File

@ -11,7 +11,6 @@
[status-im.chat.models.input :as input]
[status-im.chat.commands.receiving :as commands-receiving]
[status-im.utils.clocks :as utils.clocks]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.money :as money]
[status-im.notifications.core :as notifications]
[status-im.transport.utils :as transport.utils]
@ -19,7 +18,8 @@
[status-im.transport.message.v1.protocol :as protocol]
[status-im.data-store.messages :as messages-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
[(re-frame/inject-cofx :random-id)])
@ -35,10 +35,10 @@
(not current-chat?) (assoc :appearing? false)
(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,
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])]
{:db (update-in db
[:chats chat-id :message-groups]
@ -56,8 +56,8 @@
(assoc groups new-datemark message-refs))))
{}))}))
(defn- add-own-status
[chat-id message-id status {:keys [db]}]
(fx/defn add-own-status
[{:keys [db]} chat-id message-id status]
(let [me (:current-public-key db)
status {:chat-id chat-id
:message-id message-id
@ -71,30 +71,28 @@
(defn add-outgoing-status [{:keys [from] :as message} {:keys [db]}]
(assoc message :outgoing (= from (:current-public-key db))))
(defn- add-message
[batch? {:keys [chat-id message-id clock-value content] :as message} current-chat? {:keys [db] :as cofx}]
(fx/defn add-message
[{:keys [db] :as cofx} batch? {:keys [chat-id message-id clock-value content] :as message} current-chat?]
(let [prepared-message (-> message
(prepare-message chat-id current-chat?)
(add-outgoing-status cofx))]
(let [fx {:db (cond->
(-> db
(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)))
(not current-chat?)
(update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id))
:data-store/tx [(messages-store/save-message-tx prepared-message)]}]
(if batch?
fx
(handlers-macro/merge-fx cofx
fx
(re-index-message-groups chat-id)
(chat-loading/group-chat-messages chat-id [message]))))))
(fx/merge cofx
fx
(re-index-message-groups chat-id)
(chat-loading/group-chat-messages chat-id [message]))))))
(def ^:private- add-single-message (partial add-message false))
(def ^:private- add-batch-message (partial add-message true))
(defn- send-message-seen [chat-id message-id send-seen? cofx]
(fx/defn send-message-seen
[cofx chat-id message-id send-seen?]
(when send-seen?
(transport/send (protocol/map->MessagesSeen {:message-ids #{message-id}}) chat-id cofx)))
@ -108,7 +106,8 @@
(= constants/content-type-command-request content-type)
(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?
(let [view-id (get-in cofx [:db :view-id])
from (get-in cofx [:db :current-public-key])
@ -120,14 +119,13 @@
:to chat-id
:from from}}))))
(defn- add-received-message
[batch?
{:keys [from message-id chat-id content content-type clock-value js-obj] :as raw-message}
{:keys [db now] :as cofx}]
(fx/defn add-received-message
[{:keys [db now] :as cofx}
batch?
{: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
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])
add-message-fn (if batch? add-batch-message add-single-message)
message (-> raw-message
(commands-receiving/enhance-receive-parameters cofx)
(ensure-clock-value chat)
@ -135,57 +133,47 @@
(add-outgoing-status cofx)
;; TODO (janherich): Remove after couple of releases
update-legacy-type)]
(handlers-macro/merge-fx cofx
{:confirm-messages-processed [{:web3 web3
:js-obj js-obj}]}
(add-message-fn message current-chat?)
;; 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
;; 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
current-chat? :seen
:else :received))
(commands-receiving/receive message)
(display-notification chat-id)
(send-message-seen chat-id message-id (and (not public?)
current-chat?
(not (= constants/system from))
(not (:outgoing message)))))))
(fx/merge cofx
{:confirm-messages-processed [{:web3 web3
:js-obj js-obj}]}
(add-message batch? message current-chat?)
;; 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
;; 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
current-chat? :seen
:else :received))
(commands-receiving/receive message)
(display-notification chat-id)
(send-message-seen chat-id message-id (and (not public?)
current-chat?
(not (= constants/system from))
(not (:outgoing message)))))))
(def ^:private add-single-received-message (partial add-received-message false))
(def ^:private add-batch-received-message (partial add-received-message true))
(fx/defn receive
[{: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
[{:keys [chat-id message-id] :as message} {:keys [now] :as cofx}]
(handlers-macro/merge-fx cofx
(chat-model/upsert-chat {:chat-id chat-id
;; We activate a chat again on new messages
:is-active true
:timestamp now})
(add-single-received-message message)))
(fx/defn update-group-messages [cofx chat->message chat-id]
(fx/merge cofx
(re-index-message-groups chat-id)
(chat-loading/group-chat-messages chat-id (get chat->message chat-id))))
(defn receive-many
[messages {:keys [now] :as cofx}]
(fx/defn receive-many
[{:keys [now] :as cofx} messages]
(let [chat->message (group-by :chat-id messages)
chat-ids (keys chat->message)
chat-effects (handlers-macro/merge-effects
cofx
(fn [chat-id cofx]
(chat-model/upsert-chat {:chat-id chat-id
:is-active true
:timestamp now}
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)))
chats-fx-fns (map #(chat-model/upsert-chat {:chat-id %
:is-active true
:timestamp now}) chat-ids)
messages-fx-fns (map #(add-received-message true %) messages)
groups-fx-fns (map #(update-group-messages chat->message %) chat-ids)]
(apply fx/merge cofx (concat chats-fx-fns messages-fx-fns groups-fx-fns))))
(defn system-message [chat-id message-id timestamp content]
{:message-id message-id
@ -214,8 +202,8 @@
[(re-frame/inject-cofx :random-id)
(re-frame/inject-cofx :random-id-seq)])
(defn- send
[chat-id message-id send-record {{:keys [network-status current-public-key]} :db :as cofx}]
(fx/defn send
[{{:keys [network-status current-public-key]} :db :as cofx} chat-id message-id send-record]
(if (= network-status :offline)
{:dispatch-later [{:ms 10000
: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])
(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))
message-id (transport.utils/message-id send-record)
message-with-id (assoc message :message-id message-id)]
(handlers-macro/merge-fx cofx
(input/process-cooldown)
(chat-model/upsert-chat {:chat-id chat-id
:timestamp now})
(add-single-message message-with-id true)
(add-own-status chat-id message-id :sending)
(send chat-id message-id send-record))))
(fx/merge cofx
(input/process-cooldown)
(chat-model/upsert-chat {:chat-id chat-id
:timestamp now})
(add-message false message-with-id true)
(add-own-status chat-id message-id :sending)
(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))
{:send-notification {:message (js/JSON.stringify #js {:from (get-in cofx [:db :current-public-key])
:to (get-in cofx [:db :current-chat-id])})
@ -253,7 +241,7 @@
:sound notifications/sound-name}
: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
(get-in [:chats chat-id :message-statuses message-id from])
(assoc :status status))]
@ -262,17 +250,18 @@
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])
send-record (-> message
(select-keys transport-keys)
(update :message-type keyword)
protocol/map->Message)]
(handlers-macro/merge-fx cofx
(send chat-id message-id send-record)
(update-message-status message :sending))))
(fx/merge cofx
(send chat-id message-id send-record)
(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)]
{:db (update-in db [:chats chat-id :message-groups]
(fn [groups]
@ -285,16 +274,16 @@
(remove (comp (partial = message-id) :message-id)
message-references))))))}))
(defn delete-message
(fx/defn delete-message
"Deletes chat message, along its occurence in all references, like `:message-groups`"
[chat-id message-id {:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
{:db (update-in db [:chats chat-id :messages] dissoc 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]))))
[{:keys [db] :as cofx} chat-id message-id]
(fx/merge cofx
{:db (update-in db [:chats chat-id :messages] dissoc 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]))))
(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
{:keys [last-clock-value] :as chat} (get chats chat-id)
message-data (-> message
@ -304,4 +293,4 @@
last-clock-value)
:show? true)
(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
(:require-macros [status-im.utils.handlers-macro :as handlers-macro])
(:require [re-frame.core :as re-frame]
[status-im.accounts.core :as accounts]
[status-im.accounts.create.core :as accounts.create]
@ -27,6 +26,7 @@
:as
currency-settings.models]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[taoensso.timbre :as log]))
@ -40,7 +40,7 @@
(handlers/register-handler-fx
:init.ui/data-reset-cancelled
(fn [cofx [_ encryption-key]]
(init/initialize-app encryption-key cofx)))
(init/initialize-app cofx encryption-key)))
(handlers/register-handler-fx
:init/app-started
@ -50,12 +50,12 @@
(handlers/register-handler-fx
:init.callback/get-encryption-key-success
(fn [cofx [_ encryption-key]]
(init/initialize-app encryption-key cofx)))
(init/initialize-app cofx encryption-key)))
(handlers/register-handler-fx
:init.callback/get-device-UUID-success
(fn [cofx [_ device-uuid]]
(init/set-device-uuid device-uuid cofx)))
(init/set-device-uuid cofx device-uuid)))
(handlers/register-handler-fx
:init.callback/init-store-success
@ -66,7 +66,7 @@
(handlers/register-handler-fx
:init.callback/init-store-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
:init.callback/account-change-success
@ -85,7 +85,7 @@
(re-frame/inject-cofx :data-store/all-browsers)
(re-frame/inject-cofx :data-store/all-dapp-permissions)]
(fn [cofx [_ address]]
(init/initialize-account address cofx)))
(init/initialize-account cofx address)))
(handlers/register-handler-fx
:init.callback/account-change-error
@ -102,39 +102,39 @@
(handlers/register-handler-fx
:accounts.ui/mainnet-warning-shown
(fn [cofx _]
(accounts.update/account-update {:mainnet-warning-shown? true} cofx)))
(accounts.update/account-update cofx {:mainnet-warning-shown? true} {})))
(handlers/register-handler-fx
:accounts.ui/dev-mode-switched
(fn [cofx [_ dev-mode?]]
(accounts/switch-dev-mode dev-mode? cofx)))
(accounts/switch-dev-mode cofx dev-mode?)))
(handlers/register-handler-fx
:accounts.ui/web3-opt-in-mode-switched
(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
:accounts.ui/wallet-set-up-confirmed
(fn [cofx [_ modal?]]
(accounts/confirm-wallet-set-up modal? cofx)))
(accounts/confirm-wallet-set-up cofx modal?)))
;; accounts create module
(handlers/register-handler-fx
:accounts.create.ui/next-step-pressed
(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
:accounts.create.ui/step-back-pressed
(fn [cofx [_ step password password-confirm]]
(accounts.create/step-back step cofx)))
(accounts.create/step-back cofx step)))
(handlers/register-handler-fx
:accounts.create.ui/input-text-changed
(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
: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-status)]
(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
:accounts.create.ui/create-new-account-button-pressed
@ -159,7 +159,7 @@
(handlers/register-handler-fx
:accounts.recover.ui/passphrase-input-changed
(fn [cofx [_ recovery-phrase]]
(accounts.recover/set-phrase recovery-phrase cofx)))
(accounts.recover/set-phrase cofx recovery-phrase)))
(handlers/register-handler-fx
:accounts.recover.ui/passphrase-input-blured
@ -169,7 +169,7 @@
(handlers/register-handler-fx
:accounts.recover.ui/password-input-changed
(fn [cofx [_ masked-password]]
(accounts.recover/set-password masked-password cofx)))
(accounts.recover/set-password cofx masked-password)))
(handlers/register-handler-fx
: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-status)]
(fn [cofx [_ result password]]
(accounts.recover/on-account-recovered result password cofx)))
(accounts.recover/on-account-recovered cofx result password)))
;; accounts login module
@ -204,24 +204,24 @@
(handlers/register-handler-fx
:accounts.login.callback/login-success
(fn [cofx [_ login-result]]
(accounts.login/user-login-callback login-result cofx)))
(accounts.login/user-login-callback cofx login-result)))
(handlers/register-handler-fx
:accounts.login.ui/account-selected
(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
:accounts.login.callback/get-user-password-success
(fn [cofx [_ password]]
(accounts.login/open-login-callback password cofx)))
(accounts.login/open-login-callback cofx password)))
;; accounts logout module
(handlers/register-handler-fx
:accounts.logout.ui/logout-pressed
(fn [cofx _]
(accounts.logout/show-logout-confirmation)))
(accounts.logout/show-logout-confirmation cofx)))
(handlers/register-handler-fx
:accounts.logout.ui/logout-confirmed
@ -240,17 +240,17 @@
(handlers/register-handler-fx
:mailserver.ui/user-defined-mailserver-selected
(fn [cofx [_ mailserver-id]]
(mailserver/edit mailserver-id cofx)))
(mailserver/edit cofx mailserver-id)))
(handlers/register-handler-fx
:mailserver.ui/default-mailserver-selected
(fn [cofx [_ mailserver-id]]
(mailserver/show-connection-confirmation mailserver-id cofx)))
(mailserver/show-connection-confirmation cofx mailserver-id)))
(handlers/register-handler-fx
:mailserver.ui/add-pressed
(fn [cofx _]
(navigation/navigate-to-cofx :edit-mailserver nil cofx)))
(navigation/navigate-to-cofx cofx :edit-mailserver nil)))
(handlers/register-handler-fx
:mailserver.ui/save-pressed
@ -261,7 +261,7 @@
(handlers/register-handler-fx
:mailserver.ui/input-changed
(fn [cofx [_ input-key value]]
(mailserver/set-input input-key value cofx)))
(mailserver/set-input cofx input-key value)))
(handlers/register-handler-fx
:mailserver.ui/delete-confirmed
@ -271,22 +271,22 @@
(handlers/register-handler-fx
:mailserver.ui/delete-pressed
(fn [cofx [_ mailserver-id]]
(mailserver/show-delete-confirmation mailserver-id cofx)))
(mailserver/show-delete-confirmation cofx mailserver-id)))
(handlers/register-handler-fx
:mailserver.callback/qr-code-scanned
(fn [cofx [_ _ url]]
(mailserver/set-url-from-qr url cofx)))
(mailserver/set-url-from-qr cofx url)))
(handlers/register-handler-fx
:mailserver.ui/connect-pressed
(fn [cofx [_ mailserver-id]]
(mailserver/show-connection-confirmation mailserver-id cofx)))
(mailserver/show-connection-confirmation cofx mailserver-id)))
(handlers/register-handler-fx
:mailserver.ui/connect-confirmed
(fn [cofx [_ current-fleet mailserver-id]]
(mailserver/save-settings current-fleet mailserver-id cofx)))
(mailserver/save-settings cofx current-fleet mailserver-id)))
;; network module
@ -299,7 +299,7 @@
(handlers/register-handler-fx
:network.ui/input-changed
(fn [cofx [_ input-key value]]
(network/set-input input-key value cofx)))
(network/set-input cofx input-key value)))
(handlers/register-handler-fx
:network.ui/add-network-pressed
@ -314,12 +314,12 @@
(handlers/register-handler-fx
:network.ui/save-non-rpc-network-pressed
(fn [cofx [_ network]]
(network/save-non-rpc-network network cofx)))
(network/save-non-rpc-network cofx network)))
(handlers/register-handler-fx
:network.ui/remove-network-confirmed
(fn [cofx [_ network]]
(network/remove-network network cofx)))
(network/remove-network cofx network)))
(handlers/register-handler-fx
:network.ui/connect-network-pressed
@ -334,46 +334,46 @@
(handlers/register-handler-fx
:network/connection-status-changed
(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
:network/network-status-changed
(fn [cofx [_ data]]
(network/handle-network-status-change data cofx)))
(network/handle-network-status-change cofx data)))
;; fleet module
(handlers/register-handler-fx
:fleet.ui/save-fleet-confirmed
(fn [cofx [_ fleet]]
(fleet/save fleet cofx)))
(fleet/save cofx fleet)))
(handlers/register-handler-fx
:fleet.ui/fleet-selected
(fn [cofx [_ fleet]]
(fleet/show-save-confirmation fleet cofx)))
(fleet/show-save-confirmation cofx fleet)))
;; bootnodes module
(handlers/register-handler-fx
:bootnodes.ui/custom-bootnodes-switch-toggled
(fn [cofx [_ value]]
(bootnodes/toggle-custom-bootnodes value cofx)))
(bootnodes/toggle-custom-bootnodes cofx value)))
(handlers/register-handler-fx
:bootnodes.ui/add-bootnode-pressed
(fn [cofx [_ bootnode-id]]
(bootnodes/edit bootnode-id cofx)))
(bootnodes/edit cofx bootnode-id)))
(handlers/register-handler-fx
:bootnodes.callback/qr-code-scanned
(fn [cofx [_ _ url]]
(bootnodes/set-bootnodes-from-qr url cofx)))
(bootnodes/set-bootnodes-from-qr cofx url)))
(handlers/register-handler-fx
:bootnodes.ui/input-changed
(fn [cofx [_ input-key value]]
(bootnodes/set-input input-key value cofx)))
(bootnodes/set-input cofx input-key value)))
(handlers/register-handler-fx
:bootnodes.ui/save-pressed
@ -384,57 +384,57 @@
(handlers/register-handler-fx
:bootnodes.ui/delete-pressed
(fn [_ [_ id]]
(bootnodes/show-delete-bootnode-confirmation id)))
(bootnodes/show-delete-bootnode-confirmation _ id)))
(handlers/register-handler-fx
:bootnodes.ui/delete-confirmed
(fn [cofx [_ bootnode-id]]
(bootnodes/delete-bootnode bootnode-id cofx)))
(bootnodes/delete-bootnode cofx bootnode-id)))
;; log-level module
(handlers/register-handler-fx
:log-level.ui/change-log-level-confirmed
(fn [cofx [_ log-level]]
(log-level/save-log-level log-level cofx)))
(log-level/save-log-level cofx log-level)))
(handlers/register-handler-fx
:log-level.ui/log-level-selected
(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
(handlers/register-handler-fx
:browser.bridge.callback/qr-code-scanned
(fn [cofx [_ _ data message]]
(browser/handle-scanned-qr-code data message cofx)))
(browser/handle-scanned-qr-code cofx data message)))
;; qr-scanner module
(handlers/register-handler-fx
:qr-scanner.ui/scan-qr-code-pressed
(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
:qr-scanner.callback/scan-qr-code-success
(fn [cofx [_ context data]]
(qr-scanner/set-qr-code context data cofx)))
(qr-scanner/set-qr-code cofx context data)))
;; privacy-policy module
(handlers/register-handler-fx
:privacy-policy/privacy-policy-button-pressed
(fn [_ _]
(privacy-policy/open-privacy-policy-link)))
(fn [cofx _]
(privacy-policy/open-privacy-policy-link cofx)))
;; wallet modules
(handlers/register-handler-fx
:wallet.settings.ui/currency-selected
(fn [cofx [_ currency]]
(currency-settings.models/set-currency currency cofx)))
(currency-settings.models/set-currency cofx currency)))
;; chat module
@ -460,14 +460,14 @@
:signals/signal-received
(fn [cofx [_ event-str]]
(log/debug :event-str event-str)
(signals/process event-str cofx)))
(signals/process cofx event-str)))
;; protocol module
(handlers/register-handler-fx
:protocol.ui/close-app-confirmed
(fn [_ _]
(protocol/handle-close-app-confirmed)))
(fn [cofx _]
(protocol/handle-close-app-confirmed cofx)))
(handlers/register-handler-fx
:protocol/state-sync-timed-out
@ -486,7 +486,7 @@
(handlers/register-handler-fx
:notifications/notification-event-received
(fn [cofx [_ event]]
(notifications/handle-push-notification event cofx)))
(notifications/handle-push-notification cofx event)))
(handlers/register-handler-fx
:notifications.callback/notification-stored
@ -513,12 +513,12 @@
(handlers/register-handler-fx
:hardwallet.callback/check-nfc-support-success
(fn [cofx [_ supported?]]
(hardwallet/set-nfc-support supported? cofx)))
(hardwallet/set-nfc-support cofx supported?)))
(handlers/register-handler-fx
:hardwallet.callback/check-nfc-enabled-success
(fn [cofx [_ enabled?]]
(hardwallet/set-nfc-enabled enabled? cofx)))
(hardwallet/set-nfc-enabled cofx enabled?)))
(handlers/register-handler-fx
:hardwallet.ui/status-hardwallet-option-pressed
@ -538,14 +538,14 @@
(handlers/register-handler-fx
:hardwallet.ui/connect-info-button-pressed
(fn [cofx _]
(browser/open-url "https://hardwallet.status.im" cofx)))
(browser/open-url cofx "https://hardwallet.status.im")))
(handlers/register-handler-fx
:hardwallet.ui/hold-card-button-pressed
(fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil))))
(fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil))))
(handlers/register-handler-fx
:hardwallet.ui/begin-setup-button-pressed
@ -562,9 +562,9 @@
(handlers/register-handler-fx
:hardwallet.ui/connection-error-confirm-button-pressed
(fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil))))
(fx/merge cofx
{:db (assoc-in db [:hardwallet :setup-step] :begin)}
(navigation/navigate-to-cofx :hardwallet-setup nil))))
(handlers/register-handler-fx
:hardwallet.ui/secret-keys-next-button-pressed
@ -584,12 +584,12 @@
(handlers/register-handler-fx
:hardwallet.ui/success-button-pressed
(fn [cofx _]
(navigation/navigate-to-cofx :home nil cofx)))
(navigation/navigate-to-cofx cofx :home nil)))
(handlers/register-handler-fx
:hardwallet.ui/pin-numpad-button-pressed
(fn [cofx [_ number step]]
(hardwallet/process-pin-input number step cofx)))
(hardwallet/process-pin-input cofx number step)))
(handlers/register-handler-fx
:hardwallet.ui/pin-numpad-delete-button-pressed
@ -602,42 +602,42 @@
(handlers/register-handler-fx
:browser.ui/browser-item-selected
(fn [cofx [_ browser-id]]
(browser/open-existing-browser browser-id cofx)))
(browser/open-existing-browser cofx browser-id)))
(handlers/register-handler-fx
:browser.ui/url-input-pressed
(fn [cofx _]
(browser/update-browser-option :url-editing? true cofx)))
(browser/update-browser-option cofx :url-editing? true)))
(handlers/register-handler-fx
:browser.ui/url-input-blured
(fn [cofx _]
(browser/update-browser-option :url-editing? false cofx)))
(browser/update-browser-option cofx :url-editing? false)))
(handlers/register-handler-fx
:browser.ui/url-submitted
(fn [cofx [_ url]]
(browser/open-url-in-current-browser url cofx)))
(browser/open-url-in-current-browser cofx url)))
(handlers/register-handler-fx
:browser.ui/message-link-pressed
(fn [cofx [_ link]]
(browser/handle-message-link link cofx)))
(browser/handle-message-link cofx link)))
(handlers/register-handler-fx
:browser.ui/remove-browser-pressed
(fn [cofx [_ browser-id]]
(browser/remove-browser browser-id cofx)))
(browser/remove-browser cofx browser-id)))
(handlers/register-handler-fx
:browser.ui/lock-pressed
(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
:browser.ui/close-tooltip-pressed
(fn [cofx _]
(browser/update-browser-option :show-tooltip nil cofx)))
(browser/update-browser-option cofx :show-tooltip nil)))
(handlers/register-handler-fx
:browser.ui/previous-page-button-pressed
@ -652,12 +652,12 @@
(handlers/register-handler-fx
:browser/navigation-state-changed
(fn [cofx [_ event error?]]
(browser/navigation-state-changed event error? cofx)))
(browser/navigation-state-changed cofx event error?)))
(handlers/register-handler-fx
:browser/bridge-message-received
(fn [cofx [_ message]]
(browser/process-bridge-message message cofx)))
(browser/process-bridge-message cofx message)))
(handlers/register-handler-fx
:browser/error-occured
@ -667,49 +667,49 @@
(handlers/register-handler-fx
:browser/loading-started
(fn [cofx _]
(browser/update-browser-option :error? false cofx)))
(browser/update-browser-option cofx :error? false)))
(handlers/register-handler-fx
:browser.callback/resolve-ens-multihash-success
(fn [cofx [_ hash]]
(browser/resolve-ens-multihash-success hash cofx)))
(browser/resolve-ens-multihash-success cofx hash)))
(handlers/register-handler-fx
:browser.callback/resolve-ens-multihash-error
(fn [cofx _]
(browser/update-browser-option :resolving? false cofx)))
(browser/update-browser-option cofx :resolving? false)))
(handlers/register-handler-fx
:browser.callback/call-rpc
(fn [cofx [_ message]]
(browser/send-to-bridge message cofx)))
(browser/send-to-bridge cofx message)))
(handlers/register-handler-fx
:browser.permissions.ui/dapp-permission-allowed
(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
:browser.permissions.ui/dapp-permission-denied
(fn [cofx [_ dapp-name]]
(browser.permissions/process-next-permission dapp-name cofx)))
(browser.permissions/process-next-permission cofx dapp-name)))
(handlers/register-handler-fx
:browser.ui/open-in-status-option-selected
(fn [cofx [_ url]]
(browser/open-url url cofx)))
(browser/open-url cofx url)))
(handlers/register-handler-fx
:browser.ui/open-dapp-button-pressed
(fn [cofx [_ dapp-url]]
(browser/open-url dapp-url cofx)))
(browser/open-url cofx dapp-url)))
(handlers/register-handler-fx
:browser.ui/dapp-url-submitted
(fn [cofx [_ dapp-url]]
(browser/open-url dapp-url cofx)))
(browser/open-url cofx dapp-url)))
(handlers/register-handler-fx
:browser.ui/open-modal-chat-button-pressed
(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.i18n :as i18n]
[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]]))
(defn current-fleet
@ -40,8 +40,8 @@
{}
fleets))
(defn show-save-confirmation
[fleet {:keys [db] :as cofx}]
(fx/defn show-save-confirmation
[{:keys [db] :as cofx} fleet]
{:ui/show-confirmation {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/change-fleet
{:fleet fleet})
@ -49,12 +49,11 @@
:on-accept #(re-frame/dispatch [:fleet.ui/save-fleet-confirmed (keyword fleet)])
:on-cancel nil}})
(defn save
[fleet {:keys [db now] :as cofx}]
(fx/defn save
[{:keys [db now] :as cofx} fleet]
(let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx
(accounts.update/update-settings
(if fleet
(assoc settings :fleet fleet)
(dissoc settings :fleet))
[:accounts.update.callback/save-settings-success]))))
(accounts.update/update-settings cofx
(if fleet
(assoc settings :fleet fleet)
(dissoc settings :fleet))
{:success-event [:accounts.update.callback/save-settings-success]})))

View File

@ -1,10 +1,10 @@
(ns status-im.hardwallet.core
(:require-macros [status-im.utils.handlers-macro :as handlers-macro])
(:require [status-im.utils.platform :as platform]
[status-im.utils.config :as config]
(:require [re-frame.core :as re-frame]
[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 []
(when config/hardwallet-enabled?
@ -20,10 +20,12 @@
isEnabled
(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?)})
(defn set-nfc-enabled [enabled? {:keys [db]}]
(fx/defn set-nfc-enabled
[{:keys [db]} enabled?]
{:db (assoc-in db [:hardwallet :nfc-enabled?] enabled?)})
(defn open-nfc-settings []
@ -32,20 +34,18 @@
-default
goToNfcSetting)))
(defn navigate-to-connect-screen [cofx]
(handlers-macro/merge-fx
cofx
{:hardwallet/check-nfc-enabled nil}
(navigation/navigate-to-cofx :hardwallet-connect nil)))
(fx/defn navigate-to-connect-screen [cofx]
(fx/merge cofx
{:hardwallet/check-nfc-enabled nil}
(navigation/navigate-to-cofx :hardwallet-connect nil)))
(defn hardwallet-supported? [db]
(and config/hardwallet-enabled?
platform/android?
(get-in db [:hardwallet :nfc-supported?])))
(defn return-back-from-nfc-settings [app-coming-from-background? {:keys [db]}]
(when (and app-coming-from-background?
(= :hardwallet-connect (:view-id db)))
(fx/defn return-back-from-nfc-settings [{:keys [db]}]
(when (= :hardwallet-connect (:view-id db))
{:hardwallet/check-nfc-enabled nil}))
(defn- proceed-to-pin-confirmation [fx]
@ -61,7 +61,8 @@
:confirmation []
: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)
numbers-entered (count (get-in db' [:hardwallet :pin enter-step]))]
(cond-> {:db (assoc-in db' [:hardwallet :pin :status] nil)}

View File

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

View File

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

View File

@ -5,7 +5,8 @@
[status-im.i18n :as i18n]
[status-im.fleet.core :as fleet]
[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-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)]
(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
:mailservers/manage
@ -51,14 +52,14 @@
:id id
:name mailserver-name))
(defn connected? [id {:keys [db]}]
(defn connected? [{:keys [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]))
(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}]
(get-in db [:account/account :settings :wnode (fleet/current-fleet db)]))
@ -87,7 +88,7 @@
preference (preferred-mailserver-id cofx)
choices (-> db :inbox/wnodes current-fleet keys)]
(if (and preference
(fetch preference cofx))
(fetch cofx preference))
preference
(if current-id
(round-robin choices current-id)
@ -95,21 +96,27 @@
(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
(default? id cofx)
(connected? id cofx))
(default? cofx id)
(connected? cofx id))
{:db (update-in db [:inbox/wnodes (fleet/current-fleet db)] dissoc id)
:data-store/tx [(data-store.mailservers/delete-tx id)]})
{:dispatch [:navigate-back]}))
(defn set-current-mailserver [{:keys [db] :as cofx}]
{:db (assoc db :inbox/current-id (selected-or-random-id cofx))})
(fx/defn set-current-mailserver
[{: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}]
{:db (update-in db [:account/account :last-request] (fnil identity (quot now 1000)))})
(fx/defn set-initial-last-request
[{: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}]
(assoc-in db [:inbox/wnodes fleet id]
(-> mailserver
@ -118,20 +125,20 @@
db
mailservers)})
(defn edit [id {:keys [db] :as cofx}]
(fx/defn edit [{:keys [db] :as cofx} id]
(let [{:keys [id
address
password
name]} (fetch id cofx)
url (when address (build-url address password))
fxs (handlers-macro/merge-fx
cofx
(set-input :id id)
(set-input :url (str url))
(set-input :name (str name)))]
(assoc fxs :dispatch [:navigate-to :edit-mailserver])))
name]} (fetch cofx id)
url (when address (build-url address password))]
(fx/merge cofx
(set-input :id id)
(set-input :url (str url))
(set-input :name (str name))
(navigation/navigate-to-cofx :edit-mailserver nil))))
(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
current-fleet (fleet/current-fleet db)
mailserver (build
@ -139,7 +146,7 @@
(keyword (string/replace (:random-id cofx) "-" "")))
(:value name)
(:value url))
current (connected? (:id mailserver) cofx)]
current (connected? cofx (:id mailserver))]
{:db (-> db
(dissoc :mailservers/manage)
(assoc-in [:inbox/wnodes current-fleet (:id mailserver)] mailserver))
@ -152,8 +159,8 @@
:success-event (when current [:accounts.logout.ui/logout-confirmed])}]
:dispatch [:navigate-back]}))
(defn show-connection-confirmation
[mailserver-id {:keys [db]}]
(fx/defn show-connection-confirmation
[{:keys [db]} mailserver-id]
(let [current-fleet (fleet/current-fleet db)]
{:ui/show-confirmation
{: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-cancel nil}}))
(defn show-delete-confirmation
[mailserver-id {:keys [db]}]
(fx/defn show-delete-confirmation
[{:keys [db]} mailserver-id]
{:ui/show-confirmation
{:title (i18n/label :t/delete-mailserver-title)
:content (i18n/label :t/delete-mailserver-are-you-sure)
:confirm-button-text (i18n/label :t/delete-mailserver)
:on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}})
(defn save-settings
[current-fleet mailserver-id {:keys [db] :as cofx}]
(fx/defn save-settings
[{:keys [db] :as cofx} current-fleet mailserver-id]
(let [settings (get-in db [:account/account :settings])]
(handlers-macro/merge-fx cofx
(accounts.update/update-settings
(assoc-in settings [:wnode current-fleet] mailserver-id)
[:accounts.update.callback/save-settings-success]))))
(accounts.update/update-settings cofx
(assoc-in settings [:wnode current-fleet] mailserver-id)
{:success-event [:accounts.update.callback/save-settings-success]})))
(defn set-url-from-qr
[url cofx]
(fx/defn set-url-from-qr
[cofx url]
(assoc (set-input :url url cofx)
:dispatch [:navigate-back]))

View File

@ -3,7 +3,7 @@
[status-im.transport.message.core :as transport]
[status-im.transport.message.v1.contact :as message.v1.contact]
[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?]}]
(and (not dapp?)
@ -24,7 +24,7 @@
:address address
: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
:pending? false
:hide-contact? false
@ -35,17 +35,18 @@
(assoc-in [:contacts/new-identity] ""))
: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?
(if pending?
(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))))
(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)]
(handlers-macro/merge-fx cofx
(add-new-contact contact)
(send-contact-request contact))))
(fx/merge cofx
(add-new-contact contact)
(send-contact-request contact))))
(defn handle-contact-update
[public-key
@ -76,18 +77,17 @@
(:address contact)
(utils.contacts/public-key->address public-key))
: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)}
fcm-token (assoc :fcm-token fcm-token))]
;;NOTE (yenda) only update if there is changes to the contact
(when-not (= contact-props
(select-keys contact [:whisper-identity :public-key :address
:photo-path :name :fcm-token :pending?]))
(handlers-macro/merge-fx cofx
{:db (update-in db [:contacts/contacts public-key]
merge contact-props)
:data-store/tx [(contacts-store/save-contact-tx
contact-props)]}))))))
{:db (update-in db [:contacts/contacts public-key]
merge contact-props)
:data-store/tx [(contacts-store/save-contact-tx
contact-props)]})))))
(def receive-contact-request 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]}]
(let [contacts-list (map #(vector (:whisper-identity %) %) all-contacts)
contacts (into {} contacts-list)]

View File

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

View File

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

View File

@ -7,7 +7,8 @@
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens]
[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))
@ -186,7 +187,7 @@
(defn tokens-symbols [v 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}]
(let [network (get-in db [:account/account :networks network])
chain (ethereum/network->chain-keyword network)

View File

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

View File

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

View File

@ -5,7 +5,7 @@
[taoensso.timbre :as log]
[status-im.chat.models :as chat-model]
[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
;; with Firebase Cloud Messaging.
@ -73,7 +73,7 @@
(then #(log/debug "Notification channel created:" 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])
vals
(filter #(= (:public-key %) to))
@ -82,15 +82,16 @@
{:db (assoc-in db [:push-notifications/stored to] from)
: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])]
(if current-public-key
;; TODO(yenda) why do we ignore the notification if
;; it is not for the current account ?
(when (= to current-public-key)
(handlers-macro/merge-fx cofx
{:db (update db :push-notifications/stored dissoc to)}
(chat-model/navigate-to-chat from nil)))
(fx/merge cofx
{:db (update db :push-notifications/stored dissoc to)}
(chat-model/navigate-to-chat from nil)))
(store-event event cofx))))
(defn parse-notification-payload [s]
@ -150,14 +151,14 @@
(then #(log/debug "Display Notification" 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?
(let [to (get-in cofx [:db :accounts/accounts address :public-key])
from (get-in cofx [:db :push-notifications/stored to])]
(when from
(handle-push-notification {:from from
:to to}
cofx)))))
(handle-push-notification cofx
{:from from
:to to})))))
(re-frame/reg-fx
:notifications/display-notification

View File

@ -1,6 +1,7 @@
(ns status-im.privacy-policy.core
(: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")
@ -12,5 +13,5 @@
(fn []
(open-privacy-policy-link!)))
(defn open-privacy-policy-link []
(fx/defn open-privacy-policy-link [_]
{:privacy-policy/open-privacy-policy-link nil})

View File

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

View File

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

View File

@ -5,45 +5,45 @@
[status-im.node.core :as node]
[status-im.transport.handlers :as transport.handlers]
[status-im.transport.inbox :as inbox]
[status-im.utils.handlers-macro :as handlers-macro]
[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}]
(let [fx {:db (assoc db :status-node-started? true)}]
(if (:password (accounts.db/credentials cofx))
(handlers-macro/merge-fx cofx
fx
(accounts.login/login))
fx)))
(fx/merge cofx
{:db (assoc db :status-node-started? true)}
#(when (:password (accounts.db/credentials cofx))
(accounts.login/login %))))
(defn status-node-stopped
(fx/defn status-node-stopped
[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)
: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)
peers-count (count peers-summary)]
(handlers-macro/merge-fx cofx
{:db (assoc db
:peers-summary peers-summary
:peers-count peers-count)}
(transport.handlers/resend-contact-messages previous-summary)
(inbox/peers-summary-change-fx previous-summary))))
(fx/merge cofx
{:db (assoc db
:peers-summary peers-summary
:peers-count peers-count)}
(transport.handlers/resend-contact-messages 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)]
(case type
"node.started" (status-node-started cofx)
"node.stopped" (status-node-stopped cofx)
"module.initialized" (status-module-initialized cofx)
"envelope.sent" (transport.handlers/update-envelope-status (:hash event) :sent cofx)
"envelope.expired" (transport.handlers/update-envelope-status (:hash event) :sent cofx)
"discovery.summary" (summary event cofx)
"envelope.sent" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
"envelope.expired" (transport.handlers/update-envelope-status cofx (:hash event) :sent)
"discovery.summary" (summary cofx event)
(log/debug "Event " type " not handled"))))

View File

@ -8,15 +8,15 @@
[status-im.transport.inbox :as inbox]
[status-im.transport.utils :as transport.utils]
[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:
- adding fixed shh discovery filter
- restoring existing symetric keys along with their unique filters
- (optionally) initializing offline inboxing"
[current-account-id {:keys [db web3] :as cofx}]
[{:keys [db web3] :as cofx} current-account-id]
(log/debug :init-whisper)
(when-let [public-key (get-in db [:account/account :public-key])]
(let [sym-key-added-callback (fn [chat-id sym-key sym-key-id]
@ -24,15 +24,15 @@
:sym-key sym-key
:sym-key-id sym-key-id}]))
topic (transport.utils/get-topic constants/contact-discovery)]
(handlers-macro/merge-fx cofx
{:shh/add-discovery-filter {:web3 web3
:private-key-id public-key
:topic topic}
:shh/restore-sym-keys {:web3 web3
:transport (:transport/chats db)
:on-success sym-key-added-callback}}
(inbox/connect-to-mailserver)
(transport.handlers/resend-contact-messages)))))
(fx/merge cofx
{:shh/add-discovery-filter {:web3 web3
:private-key-id public-key
:topic topic}
:shh/restore-sym-keys {:web3 web3
:transport (:transport/chats db)
:on-success sym-key-added-callback}}
(inbox/connect-to-mailserver)
(transport.handlers/resend-contact-messages [])))))
;;TODO (yenda) remove once go implements persistence
;;Since symkeys are not persisted, we restore them via add sym-keys,
@ -61,7 +61,7 @@
(fn [js-error js-message]
(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
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

View File

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

View File

@ -1,23 +1,18 @@
(ns ^{:doc "Offline inboxing events and API"}
status-im.transport.inbox
(: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.data-store.accounts :as accounts-store]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.data-store.core :as data-store]
[status-im.mailserver.core :as mailserver]
[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 ?
;;
@ -76,7 +71,8 @@
(error-fn error)
(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)]
{: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/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]
{:db (assoc db
:mailserver-status state
: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)
{:shh/generate-sym-key-from-password
[{:password (:password wnode)
@ -173,7 +169,7 @@
(re-frame/dispatch [:inbox/get-sym-key-success wnode sym-key-id]))
: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
it doesn't exists
Peer summary will change and we will receive a signal from status go when
@ -186,21 +182,21 @@
peers-summary (:peers-summary db)
connected? (registered-peer? peers-summary address)]
(if connected?
(handlers-macro/merge-fx cofx
(update-mailserver-status :connected)
(generate-mailserver-symkey wnode))
(handlers-macro/merge-fx cofx
{::add-peer {:wnode address}
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/check-connection]}]}
(update-mailserver-status :connecting)
(generate-mailserver-symkey wnode)))))
(fx/merge cofx
(update-mailserver-status :connected)
(generate-mailserver-symkey wnode))
(fx/merge cofx
{::add-peer {:wnode address}
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/check-connection]}]}
(update-mailserver-status :connecting)
(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:
- mailserver disconnected: we try to reconnect
- 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)
(let [{:keys [peers-summary peers-count]} db
wnode (:address (mailserver/fetch-current cofx))
@ -245,35 +241,32 @@
(defn request-history-span [now-in-s]
(- now-in-s one-day))
(defn request-messages
([{:keys [db now] :as cofx}]
(let [wnode (mailserver/fetch-current cofx)
web3 (:web3 db)
now-in-s (quot now 1000)
last-request (max
(get-in db [:account/account :last-request])
(- now-in-s seven-days))
request-messages-topics (get-request-messages-topics db)
request-history-topics (get-request-history-topics db)]
(when (inbox-ready? wnode cofx)
{::request-messages [{:wnode wnode
:topics request-messages-topics
:from last-request
:to now-in-s
:web3 web3}
{:wnode wnode
:from (request-history-span now-in-s)
:to now-in-s
:topics request-history-topics
:web3 web3}]
:db (assoc db :inbox/fetching? true)
:dispatch-later [{:ms fetching-timeout
:dispatch [:inbox/check-fetching now-in-s]}]})))
([should-recover? {:keys [db] :as cofx}]
(when should-recover?
(request-messages cofx))))
(fx/defn request-messages
[{:keys [db now] :as cofx}]
(let [wnode (mailserver/fetch-current cofx)
web3 (:web3 db)
now-in-s (quot now 1000)
last-request (max
(get-in db [:account/account :last-request])
(- now-in-s seven-days))
request-messages-topics (get-request-messages-topics db)
request-history-topics (get-request-history-topics db)]
(when (inbox-ready? wnode cofx)
{::request-messages [{:wnode wnode
:topics request-messages-topics
:from last-request
:to now-in-s
:web3 web3}
{:wnode wnode
:from (request-history-span now-in-s)
:to now-in-s
:topics request-history-topics
:web3 web3}]
:db (assoc db :inbox/fetching? true)
:dispatch-later [{:ms fetching-timeout
:dispatch [:inbox/check-fetching now-in-s]}]})))
(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)
web3 (:web3 db)
topic (get-in db [:transport/chats chat-id :topic])
@ -293,33 +286,34 @@
(handlers/register-handler-fx
:inbox/mailserver-trusted
(fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx
(update-mailserver-status :connected)
(request-messages))))
(fx/merge cofx
(update-mailserver-status :connected)
(request-messages))))
(handlers/register-handler-fx
:inbox/get-sym-key-success
(fn [{:keys [db] :as cofx} [_ wnode sym-key-id]]
(handlers-macro/merge-fx cofx
(add-sym-key-id-to-wnode wnode sym-key-id)
(request-messages))))
(fx/merge cofx
(add-sym-key-id-to-wnode wnode sym-key-id)
(request-messages))))
(handlers/register-handler-fx
:inbox/request-chat-history
(fn [{:keys [db] :as cofx} [_ chat-id]]
(request-chat-history chat-id cofx)))
(request-chat-history cofx chat-id)))
(handlers/register-handler-fx
:inbox/check-connection
(fn [{:keys [db] :as cofx} _]
(when (= :connecting (:mailserver-status db))
(if (mailserver/preferred-mailserver-id cofx)
(update-mailserver-status :error cofx)
(handlers-macro/merge-fx cofx
(mailserver/set-current-mailserver)
(connect-to-mailserver))))))
(update-mailserver-status cofx :error)
(fx/merge cofx
(mailserver/set-current-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)
transport-txs (reduce (fn [txs [chat-id chat]]
(if (:fetch-history? chat)
@ -346,7 +340,7 @@
:last-request last-request))]
: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
[:transport/chats chat-id :fetch-history?]
false)
@ -355,11 +349,11 @@
:chat (assoc (get-in db [:transport/chats chat-id])
:fetch-history? false)})]})
(defn initialize-offline-inbox [custom-mailservers cofx]
(handlers-macro/merge-fx cofx
(mailserver/add-custom-mailservers custom-mailservers)
(mailserver/set-initial-last-request)
(mailserver/set-current-mailserver)))
(fx/defn initialize-offline-inbox [cofx custom-mailservers]
(fx/merge cofx
(mailserver/add-custom-mailservers custom-mailservers)
(mailserver/set-initial-last-request)
(mailserver/set-current-mailserver)))
(handlers/register-handler-fx
:inbox/check-fetching
@ -371,12 +365,12 @@
(let [time-since-last-received (- now (:inbox/last-received db))]
(if (> time-since-last-received fetching-timeout)
(if chat-id
(handlers-macro/merge-fx cofx
{:db (assoc db :inbox/fetching? false)}
(update-fetch-history chat-id))
(handlers-macro/merge-fx cofx
{:db (assoc db :inbox/fetching? false)}
(update-last-request last-request)))
(fx/merge cofx
{:db (assoc db :inbox/fetching? false)}
(update-fetch-history chat-id))
(fx/merge cofx
{:db (assoc db :inbox/fetching? false)}
(update-last-request last-request)))
{:dispatch-later [{:ms (- fetching-timeout
time-since-last-received)
: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.v1.protocol :as protocol]
[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]
message/StatusMessage
@ -18,12 +19,12 @@
:chat-id chat-id
:topic topic
:message this}]))]
(handlers-macro/merge-fx cofx
{:shh/get-new-sym-keys [{:web3 (:web3 db)
:on-success on-success}]}
(protocol/init-chat {:chat-id chat-id
:topic topic
:resend? "contact-request"})))))
(fx/merge cofx
{:shh/get-new-sym-keys [{:web3 (:web3 db)
:on-success on-success}]}
(protocol/init-chat {:chat-id chat-id
:topic topic
:resend? "contact-request"})))))
(defrecord ContactRequestConfirmed [name profile-image address fcm-token]
message/StatusMessage
@ -31,15 +32,15 @@
(let [success-event [:transport/set-contact-message-envelope-hash chat-id]
chat (get-in db [:transport/chats chat-id])
updated-chat (assoc chat :resend? "contact-request-confirmation")]
(handlers-macro/merge-fx cofx
{:db (assoc-in db
[:transport/chats chat-id :resend?]
"contact-request-confirmation")
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event})))))
(fx/merge cofx
{:db (assoc-in db
[:transport/chats chat-id :resend?]
"contact-request-confirmation")
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event})))))
(defrecord ContactUpdate [name profile-image address fcm-token]
message/StatusMessage
@ -59,36 +60,37 @@
tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]
success-event [:transport/set-contact-message-envelope-hash chat-id]]
(handlers-macro/merge-fx temp-cofx
{:db (assoc-in db
[:transport/chats chat-id :resend?]
"contact-update")
:data-store/tx tx}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event}))))
(fx/merge temp-cofx
{:db (assoc-in db
[:transport/chats chat-id :resend?]
"contact-update")
:data-store/tx tx}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event}))))
recipients))))
(defn remove-chat-filter
(fx/defn remove-chat-filter
"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])]
{:shh/remove-filter filter}))
(defn init-chat
[chat-id topic cofx]
(fx/defn init-chat
[cofx chat-id topic]
(when-not (get-in cofx [:db :transport/chats chat-id])
(protocol/init-chat {:chat-id chat-id
:topic topic} cofx)))
(protocol/init-chat cofx
{:chat-id chat-id
:topic topic})))
(defrecord NewContactKey [sym-key topic message]
message/StatusMessage
(send [this chat-id cofx]
(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
:success-event success-event}
cofx)))
:success-event success-event})))
(receive [this chat-id _ timestamp {:keys [db] :as cofx}]
(let [current-sym-key (get-in db [:transport/chats chat-id :sym-key])
;; NOTE(yenda) to support concurrent contact request without additional
@ -109,14 +111,14 @@
:chat-id chat-id
:topic topic
:message message}]))]
(handlers-macro/merge-fx cofx
{:shh/add-new-sym-keys [{:web3 (:web3 db)
:sym-key sym-key
:on-success on-success}]}
(init-chat chat-id topic)
;; in case of concurrent contact request we want
;; to stop the filter for the previous key before
;; dereferrencing it
(remove-chat-filter chat-id)))
(fx/merge cofx
{:shh/add-new-sym-keys [{:web3 (:web3 db)
:sym-key sym-key
:on-success on-success}]}
(init-chat chat-id topic)
;; in case of concurrent contact request we want
;; to stop the filter for the previous key before
;; dereferrencing it
(remove-chat-filter chat-id)))
;; if we don't save the key, we read the message directly
(message/receive message chat-id chat-id timestamp cofx)))))

View File

@ -1,10 +1,10 @@
(ns ^{:doc "Group chat API"}
status-im.transport.message.v1.group-chat
(: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.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.
;; 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}
cofx)))
(receive [this _ signature timestamp {:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
{:shh/add-new-sym-keys
[{:web3 (:web3 db)
:sym-key sym-key
:on-success (fn [sym-key sym-key-id]
(re-frame/dispatch
[:group/add-new-sym-key
{:chat-id chat-id
:signature signature
:timestamp timestamp
:sym-key sym-key
:sym-key-id sym-key-id
:message message}]))}]}
(protocol/init-chat {:chat-id chat-id}))))
(fx/merge cofx
{:shh/add-new-sym-keys
[{:web3 (:web3 db)
:sym-key sym-key
:on-success (fn [sym-key sym-key-id]
(re-frame/dispatch
[:group/add-new-sym-key
{:chat-id chat-id
:signature signature
:timestamp timestamp
:sym-key sym-key
:sym-key-id sym-key-id
:message message}]))}]}
(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 :current-public-key])))
(defn send-new-group-key [message chat-id cofx]
(when (user-is-group-admin? chat-id cofx)
(fx/defn send-new-group-key
[message chat-id cofx]
(when (user-is-group-admin? cofx chat-id)
{:shh/get-new-sym-keys [{:web3 (get-in cofx [:db :web3])
:on-success (fn [sym-key sym-key-id]
(re-frame/dispatch
@ -51,21 +51,18 @@
:sym-key-id sym-key-id
: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]
message/StatusMessage
(send [this chat-id cofx]
(handlers-macro/merge-fx cofx
(init-chat-if-new chat-id)
(send-new-group-key this chat-id))))
(fx/merge cofx
#(when (nil? (get-in % [:db :transport/chats chat-id]))
(protocol/init-chat {:chat-id chat-id} %))
(send-new-group-key this chat-id))))
(defrecord GroupLeave []
message/StatusMessage
(send [this chat-id cofx]
(protocol/send {:chat-id chat-id
(protocol/send cofx
{:chat-id chat-id
:payload this
:success-event [:group/unsubscribe-from-chat chat-id]}
cofx)))
:success-event [:group/unsubscribe-from-chat chat-id]})))

View File

@ -5,33 +5,28 @@
[status-im.chat.core :as chat]
[status-im.transport.db :as transport.db]
[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
{:ttl 10 ;; ttl of 10 sec
:powTarget config/pow-target
:powTime config/pow-time})
(defn init-chat
(fx/defn init-chat
"Initialises chat on protocol layer.
If topic is not passed as argument it is derived from `chat-id`"
[{:keys [chat-id topic resend?]
:or {topic (transport.utils/get-topic chat-id)}}
{:keys [db]}]
[{:keys [db]}
{:keys [chat-id topic resend?]
:or {topic (transport.utils/get-topic chat-id)}}]
{:db (assoc-in db
[:transport/chats chat-id]
(transport.db/create-chat {:topic topic
:resend? resend?}))})
#_(defn requires-ack [message-id chat-id {:keys [db] :as cofx}]
{: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
(fx/defn send
"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
(let [{:keys [current-public-key web3]} db
{:keys [sym-key-id topic]} (get-in db [:transport/chats chat-id])]
@ -43,9 +38,9 @@
:topic topic}
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"
[{: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]
{:shh/post [{:web3 web3
:success-event success-event
@ -60,9 +55,9 @@
(select-keys (get-in db [:transport/chats public-key]) [:topic :sym-key-id]))
public-keys))
(defn multi-send-by-pubkey
(fx/defn multi-send-by-pubkey
"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
recipients (prepare-recipients public-keys db)]
{:shh/multi-post {:web3 web3
@ -95,8 +90,8 @@
group-chat (get-in cofx [:db :chats chat-id :group-chat])]
(if (or group-chat
config/use-sym-key)
(send params cofx)
(send-with-pubkey params cofx))))
(send cofx params)
(send-with-pubkey cofx params))))
(receive [this chat-id signature _ cofx]
{:chat-received-message/add-fx
[(assoc (into {} this)
@ -109,8 +104,8 @@
(defrecord MessagesSeen [message-ids]
message/StatusMessage
(send [this chat-id cofx]
(send {:chat-id chat-id
:payload this}
cofx))
(send cofx
{:chat-id chat-id
:payload this}))
(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"}
status-im.transport.message.v1.public-chat
(:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.transport.message.core :as message]
[status-im.data-store.transport :as transport-store]
[status-im.transport.message.v1.protocol :as protocol]
[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]))
(defn join-public-chat
(fx/defn join-public-chat
"Function producing all protocol level effects necessary for joining public chat identified by chat-id"
[chat-id {:keys [db] :as cofx}]
(when-not (has-already-joined? chat-id cofx)
[{:keys [db] :as cofx} chat-id]
(when-not (has-already-joined? cofx chat-id)
(let [on-success (fn [sym-key sym-key-id]
(re-frame/dispatch [::add-new-sym-key {:chat-id chat-id
:sym-key sym-key
:sym-key-id sym-key-id}]))]
(handlers-macro/merge-fx cofx
{:shh/generate-sym-key-from-password [{:web3 (:web3 db)
:password chat-id
:on-success on-success}]}
(protocol/init-chat {:chat-id chat-id})))))
(fx/merge cofx
{:shh/generate-sym-key-from-password [{:web3 (:web3 db)
:password chat-id
:on-success on-success}]}
(protocol/init-chat {:chat-id chat-id})))))
(handlers/register-handler-fx
::add-new-sym-key

View File

@ -4,11 +4,12 @@
[cljs-time.core :refer [now]]
[clojure.string :as string]
[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"
[chat-id {:keys [db]}]
[{:keys [db]} chat-id]
(let [filter (get-in db [:transport/chats chat-id :filter])]
{:db (update db :transport/chats dissoc 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
(:require [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]))
(:require [status-im.utils.handlers :as handlers]))
(handlers/register-handler-fx
:show-desktop-tab

View File

@ -7,4 +7,4 @@
:handle-qr-code
(fn [cofx [_ _ 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.ui.screens.navigation :as navigation]
[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)
(universal-links/handle-view-profile data cofx)
(or (universal-links/handle-url data cofx)
(universal-links/handle-view-profile cofx data)
(or (universal-links/handle-url cofx data)
{:utils/show-popup [(i18n/label :t/unable-to-read-this-code)
(i18n/label :t/use-valid-qr-code {:data data})
#(re-frame/dispatch [:navigate-to-clean :home])]})))
(defn handle-qr-code [data cofx]
(handlers-macro/merge-fx cofx
(navigation/navigate-to-clean :home)
(process-qr-code data)))
(fx/defn handle-qr-code
[cofx data]
(fx/merge cofx
(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
(: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.utils.ethereum.stateofus :as stateofus]
[status-im.utils.ethereum.core :as ethereum]
[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
:resolve-whisper-identity

View File

@ -7,15 +7,15 @@
[status-im.ui.screens.browser.default-dapps :as default-dapps]
[status-im.ui.screens.navigation :as navigation]
[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.utils :as utils]))
[status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]))
(defn add-contact-and-open-chat [whisper-id cofx]
(handlers-macro/merge-fx
cofx
(models.contact/add-contact whisper-id)
(chat.models/start-chat whisper-id {:navigation-replace? true})))
(fx/defn add-contact-and-open-chat
[cofx whisper-id]
(fx/merge cofx
(models.contact/add-contact whisper-id)
(chat.models/start-chat whisper-id {:navigation-replace? true})))
(re-frame/reg-cofx
:get-default-contacts
@ -31,7 +31,7 @@
:add-contact
[(re-frame/inject-cofx :random-id)]
(fn [cofx [_ whisper-id]]
(models.contact/add-contact whisper-id cofx)))
(models.contact/add-contact cofx whisper-id)))
(handlers/register-handler-fx
:hide-contact
@ -48,28 +48,28 @@
validation-result (new-chat.db/validate-pub-key db contact-identity)]
(if (some? validation-result)
(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
(add-contact-and-open-chat contact-identity))))))
(fx/merge cofx
fx
(add-contact-and-open-chat contact-identity))))))
(handlers/register-handler-fx
:open-contact-toggle-list
(fn [{:keys [db] :as cofx} _]
(handlers-macro/merge-fx cofx
{:db (assoc db
:group/selected-contacts #{}
:new-chat-name "")}
(navigation/navigate-to-cofx :contact-toggle-list nil))))
(fx/merge cofx
{:db (assoc db
:group/selected-contacts #{}
:new-chat-name "")}
(navigation/navigate-to-cofx :contact-toggle-list nil))))
(handlers/register-handler-fx
:open-chat-with-contact
[(re-frame/inject-cofx :random-id)]
(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
:add-contact-handler
[(re-frame/inject-cofx :random-id)]
(fn [{{:contacts/keys [new-identity]} :db :as cofx} _]
(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
(:require [status-im.accounts.update.core :as accounts.update]
[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])
new-settings (assoc-in settings [:wallet :currency] currency)]
(handlers-macro/merge-fx cofx
(accounts.update/update-settings new-settings)
(wallet/update-wallet))))
(fx/merge cofx
(accounts.update/update-settings new-settings {})
(wallet/update-wallet))))

View File

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

View File

@ -30,9 +30,9 @@
[status-im.ui.components.permissions :as permissions]
[status-im.utils.dimensions :as dimensions]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[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]}]
(let [on-success #(re-frame/dispatch (success-event-creator %))
@ -103,13 +103,18 @@
(fn [{:keys [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}]
(let [app-coming-from-background? (= state "active")]
(handlers-macro/merge-fx cofx
{::app-state-change-fx state
:db (assoc db :app-state state)}
(inbox/request-messages app-coming-from-background?)
(hardwallet/return-back-from-nfc-settings app-coming-from-background?))))
(fx/merge cofx
{::app-state-change-fx state
:db (assoc db :app-state state)}
#(when app-coming-from-background?
(on-return-from-background %)))))
(handlers/register-handler-fx
:app-state-change

View File

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

View File

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

View File

@ -1,14 +1,17 @@
(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)
{:db (update-in db [:chats chat-id :contacts]
concat added-participants-set)
:data-store/tx [(chats-store/add-chat-contacts-tx
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)
(let [{:keys [is-active timestamp]} (get-in db [:chats chat-id])]
;;TODO: not sure what this condition is for

View File

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

View File

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

View File

@ -66,4 +66,4 @@
(handlers/register-handler-fx
:open-collectible-in-browser
(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.handlers :as handlers]
[status-im.utils.money :as money]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.prices :as prices]
[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]}]
(if (and web3 account-id)
@ -168,7 +168,7 @@
(assoc-error-message :balance-update :error-unable-to-get-balance)
(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
(assoc-in [:wallet :balance symbol] balance)
(assoc-in [:wallet :balance-loading?] false))})
@ -176,7 +176,7 @@
(handlers/register-handler-fx
:update-token-balance-success
(fn [cofx [_ symbol balance]]
(update-token-balance-success symbol balance cofx)))
(update-token-balance-success cofx symbol balance)))
(handlers/register-handler-fx
:update-token-balance-fail
@ -242,7 +242,6 @@
(handlers/register-handler-fx
:wallet-setup-navigate-back
(fn [{:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
{:db (assoc-in db [:wallet :send-transaction] {})}
(navigation/navigate-back))))
(fx/merge cofx
{:db (assoc-in db [:wallet :send-transaction] {})}
(navigation/navigate-back))))

View File

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

View File

@ -1,5 +1,4 @@
(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]
[status-im.chat.commands.sending :as commands-sending]
[status-im.chat.models.message :as models.message]
@ -13,8 +12,8 @@
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.erc20 :as erc20]
[status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.money :as money]
[status-im.utils.security :as security]
[status-im.utils.types :as types]
@ -150,8 +149,7 @@
:data data
:dapp-transaction queued-transaction
:method method})]
(navigation/navigate-to-cofx
:wallet-sign-message-modal nil {:db db''}))
(navigation/navigate-to-cofx {:db db''} :wallet-sign-message-modal nil))
{:db db'})))))))
(handlers/register-handler-fx
@ -161,12 +159,11 @@
(fn [{:keys [db] :as cofx} [_ chat-id params]]
;;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
(if-let [send-command (and chat-id (get-in db [:id->command ["send" #{:personal-chats}]]))]
(handlers-macro/merge-fx cofx
(commands-sending/send chat-id send-command params)
(navigation/navigate-to-clean :wallet-transaction-sent))
(handlers-macro/merge-fx cofx
(navigation/navigate-to-clean :wallet-transaction-sent)))))
(let [send-command? (and chat-id (get-in db [:id->command ["send" #{:personal-chats}]]))]
(fx/merge cofx
#(when send-command?
(commands-sending/send % chat-id send-command? params))
(navigation/navigate-to-clean :wallet-transaction-sent {})))))
(defn set-and-validate-amount-db [db amount symbol decimals]
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
@ -266,10 +263,9 @@
(handlers/register-handler-fx
:close-transaction-sent-screen
(fn [{:keys [db] :as cofx} [_ chat-id]]
(handlers-macro/merge-fx
cofx
{:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]}
(navigation/navigate-back))))
(fx/merge cofx
{:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]}
(navigation/navigate-back))))
(handlers/register-handler-fx
:sync-wallet-transactions

View File

@ -1,17 +1,17 @@
(ns status-im.ui.screens.wallet.settings.events
(:require [status-im.ui.screens.wallet.settings.models :as models]
[status-im.accounts.update.core :as accounts.update]
[status-im.utils.handlers :as handlers]))
(handlers/register-handler-fx
:wallet.settings/toggle-visible-token
(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
:configure-token-balance-and-visibility
(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
:wallet.ui/pull-to-refresh

View File

@ -1,29 +1,30 @@
(ns status-im.ui.screens.wallet.settings.models
(:require [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro]
(:require [re-frame.core :as re-frame]
[status-im.accounts.update.core :as accounts.update]
[status-im.ui.screens.wallet.events :as wallet.events]
[status-im.utils.ethereum.core :as ethereum]
[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?]
(if checked?
(conj (or 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))
chain (ethereum/network->chain-keyword network)
settings (get account :settings)
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]
(handlers-macro/merge-fx cofx
(toggle-visible-token symbol true update-settings-fx)
;;TODO(goranjovic): move `update-token-balance-success` function to wallet models
(wallet.events/update-token-balance-success symbol balance)))
(fx/defn configure-token-balance-and-visibility [cofx symbol balance]
(fx/merge cofx
(toggle-visible-token symbol true)
;;TODO(goranjovic): move `update-token-balance-success` function to wallet models
(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
network (get (:networks account) (:network account))
chain (ethereum/network->chain-keyword network)

View File

@ -1,7 +1,7 @@
(ns status-im.utils.fx
(:require-macros status-im.utils.fx
[taoensso.timbre :as log])
(:require [clojure.set :as set])
(:require-macros status-im.utils.fx)
(:require [clojure.set :as set]
[taoensso.timbre :as log])
(:refer-clojure :exclude [merge]))
(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
(:require-macros status-im.utils.handlers-macro
[taoensso.timbre :as log])
(:require [clojure.set :as set]))
(:require [clojure.set :as set]
[taoensso.timbre :as log]))
(defn update-db [cofx 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]}]
{:pre [(keyword? semaphore)]}
(fx/defn lock [{:keys [db]} semaphore]
#_{:pre [(keyword? semaphore)]}
{:db (update db :semaphores conj semaphore)})
(defn free [semaphore {:keys [db]}]
{:pre [(keyword? semaphore)]}
(update db :semaphores disj semaphore))
(fx/defn free [{:keys [db]} semaphore]
#_{:pre [(keyword? semaphore)]}
(println {:db (update db :semaphores disj semaphore)})
{:db (update db :semaphores disj semaphore)})
(defn locked? [semaphore cofx]
{:pre [(keyword? semaphore)]}
((get-in cofx [:db :semaphores]) semaphore))
(defn locked? [{:keys [db]} semaphore]
#_{:pre [(keyword? semaphore)]}
((get db :semaphores) semaphore))

View File

@ -1,16 +1,15 @@
(ns status-im.utils.universal-links.core
(:require
[taoensso.timbre :as log]
[re-frame.core :as re-frame]
[status-im.utils.config :as config]
[status-im.chat.events :as chat.events]
[status-im.accounts.db :as accounts.db]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.utils.handlers-macro :as handlers-macro]
[cljs.spec.alpha :as spec]
[status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db]))
(:require [cljs.spec.alpha :as spec]
[re-frame.core :as re-frame]
[status-im.accounts.db :as accounts.db]
[status-im.chat.events :as chat.events]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.config :as config]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link
@ -37,21 +36,21 @@
;; as it is opened in safari on iOS
(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)
{: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)
(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)
(if (new-chat.db/own-whisper-identity? db profile-id)
(navigation/navigate-to-cofx :my-profile nil cofx)
(chat.events/show-profile profile-id cofx)))
(navigation/navigate-to-cofx cofx :my-profile nil)
(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)
{:extension/load [url :extensions/stage]})
@ -65,45 +64,45 @@
(re-frame/dispatch [:handle-universal-link 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"
[url cofx]
[cofx url]
(cond
(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))
(handle-view-profile (match-url url profile-regex) cofx)
(handle-view-profile cofx (match-url url profile-regex))
(match-url url browse-regex)
(handle-browse url cofx)
(handle-browse cofx url)
(and config/extensions-enabled? (match-url url extension-regex))
(handle-extension url cofx)
(handle-extension cofx 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"
[url {:keys [db]}]
[{:keys [db]} url]
(log/info :store-url-for-later)
{: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
on login, otherwise just handle it"
[url cofx]
[cofx url]
(if (accounts.db/logged-in? cofx)
(route-url url cofx)
(store-url-for-later url cofx)))
(route-url cofx url)
(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"
[{:keys [db] :as cofx}]
(when-let [url (:universal-links/url db)]
(handlers-macro/merge-fx cofx
{:db (dissoc db :universal-links/url)}
(handle-url url))))
(fx/merge cofx
{:db (dissoc db :universal-links/url)}
(handle-url url))))
(defn unwrap-js-url [e]
(-> e

View File

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

View File

@ -44,19 +44,19 @@
(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 {}})))
(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"
: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"
: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 "
: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"
: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
(is (= {:db {:accounts/recover {:passphrase-error nil
@ -75,13 +75,13 @@
(deftest set-password
(is (= {:db {:accounts/recover {:password " "
:password-valid? false}}}
(models/set-password (security/mask-data " ") {:db {}})))
(models/set-password {:db {}} (security/mask-data " "))))
(is (= {:db {:accounts/recover {:password "abc"
: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"
:password-valid? true}}}
(models/set-password (security/mask-data "thisisapaswoord") {:db {}}))))
(models/set-password {:db {}} (security/mask-data "thisisapaswoord")))))
(deftest validate-password
(is (= {:db {:accounts/recover {:password " "

View File

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

View File

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

View File

@ -65,7 +65,7 @@
(def AnotherTestCommandInstance (AnotherTestCommand.))
(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"
(is (= TestCommandInstance
(get-in fx [:db :id->command
@ -94,7 +94,7 @@
(core/command-id AnotherTestCommandInstance))))))
(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"
(is (= #{TestCommandInstance AnotherTestCommandInstance}
(into #{}

View File

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

View File

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

View File

@ -12,7 +12,7 @@
cofx {:now "now"
:db {:contacts/contacts {chat-id
{: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])
store-chat-fx (:data-store/tx response)]
(testing "it adds the chat to the chats collection"
@ -36,7 +36,7 @@
:extra-prop "some"}
cofx {:db {:chats {chat-id {:is-active true
: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])
store-chat-fx (:data-store/tx response)]
(testing "it adds the chat to the chats collection"
@ -57,16 +57,16 @@
:db {:chats {chat-id {:is-active false
:name "old-name"}}}}]
(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"
(is (= {:db (:db cofx)} (chat/upsert-chat chat-props cofx)))))))
(is (= {:db (:db cofx)} (chat/upsert-chat cofx chat-props)))))))
(deftest add-group-chat
(let [chat-id "chat-id"
chat-name "chat-name"
admin "admin"
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)
group-chat (get-in fx [:db :chats chat-id])]
(testing "it saves the chat in the database"
@ -86,7 +86,7 @@
(deftest add-public-chat
(let [topic "topic"
fx (chat/add-public-chat topic {})
fx (chat/add-public-chat {:db {}} topic)
store-fx (:data-store/tx fx)
chat (get-in fx [:db :chats topic])]
(testing "it saves the chat in the database"
@ -111,38 +111,38 @@
:unviewed-messages #{"3"}
:not-loaded-message-ids #{"2" "3"}}}}}]
(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])))))
(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])))))
(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])))))
(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])))))
(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])))))
(testing "it does not override the deleted-at-clock-value when there are no messages"
(let [actual (chat/clear-history chat-id
(update-in cofx
(let [actual (chat/clear-history (update-in cofx
[:db :chats chat-id]
assoc
: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])))))
(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)]
(let [actual (chat/clear-history chat-id
(update-in cofx
(let [actual (chat/clear-history (update-in cofx
[:db :chats chat-id]
assoc
:messages {}))]
:messages {})
chat-id)]
(is (= 42 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))))
(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 (= 2 (count (:data-store/tx actual))))))))
@ -153,37 +153,37 @@
"2" {:clock-value 10}
"3" {:clock-value 2}}}}}}]
(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])))))
(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])))))
(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])))))
(testing "it removes it from transport if it's a public chat"
(let [actual (chat/remove-chat chat-id
(update-in
(let [actual (chat/remove-chat (update-in
cofx
[:db :chats chat-id]
assoc
:group-chat true
:public? true))]
:public? true)
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"
(let [actual (chat/remove-chat chat-id
(assoc-in
(let [actual (chat/remove-chat (assoc-in
cofx
[:db :chats chat-id :group-chat]
true))]
true)
chat-id)]
(is (:shh/post actual))
(testing "it does not remove transport, only after send is successful"
(is (get-in actual [:db :transport/chats chat-id])))))
(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]))))
(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 (= 3 (count (:data-store/tx actual))))))))
@ -191,25 +191,25 @@
(let [chat-id "1"]
(testing "it returns true if it's a group chat"
(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"
(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"
(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?
(let [chat-id "1"]
(testing "it returns true if it's a group chat"
(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"
(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"
(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
{:current-public-key "me"
@ -248,7 +248,7 @@
(deftest mark-messages-seen
(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)]
(is (= '(:seen :seen :seen)
(map (fn [[_ v]]
@ -259,9 +259,9 @@
(is (= #{"3" "2" "1"} (get-in fx [:db :chats "status" :unviewed-messages])))))
(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"
(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]))))))

View File

@ -37,7 +37,7 @@
(testing "New messages are grouped/sorted correctly, hidden messages are not grouped"
(is (= '(2 3)
(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])
first
second)))))))

View File

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

View File

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

View File

@ -5,6 +5,6 @@
(deftest initialize-account-db
(testing "it preserves universal-links/url"
(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])))))

View File

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

View File

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

View File

@ -86,13 +86,13 @@
:error true}
:chain {:value "mainnet"
:error false}}}}
(model/set-input :url "http://valid.com"
{:db {:networks/manage {:url {:value "something"
(model/set-input {:db {:networks/manage {:url {:value "something"
:error true}
:name {:value ""
:error false}
:chain {:value "mainnet"
:error false}}}})))))
:error false}}}}
:url "http://valid.com")))))
(deftest save
(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"}}}}]
(testing "installation-id"
(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)))))
(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))))))
(testing "pfs & group chats disabled"
(with-redefs [config/pfs-encryption-enabled? false
config/group-chats-enabled? false]
(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)))))
(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))))))
(testing "pfs is enabled"
(with-redefs [config/pfs-encryption-enabled? true]
(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)))))
(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))))))
(testing "group chats is enabled"
(with-redefs [config/group-chats-enabled? true]
(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)))))
(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)))))))))

View File

@ -33,7 +33,6 @@
[status-im.test.protocol.web3.inbox]
[status-im.test.utils.utils]
[status-im.test.utils.money]
[status-im.test.utils.handlers-macro]
[status-im.test.utils.clocks]
[status-im.test.utils.ethereum.eip681]
[status-im.test.utils.ethereum.core]
@ -98,7 +97,6 @@
'status-im.test.transport.handlers
'status-im.test.protocol.web3.inbox
'status-im.test.utils.utils
'status-im.test.utils.handlers-macro
'status-im.test.utils.money
'status-im.test.utils.clocks
'status-im.test.utils.ethereum.eip681

View File

@ -7,9 +7,9 @@
(let [cofx {:db {:account/account {:public-key "1"}
:semaphores #{}}}]
(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"
(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"
(let [ms-1 {:id "1"
:fleet :eth.beta
@ -42,5 +42,5 @@
ms-3])]
(is (= expected-wnodes
(get-in
(protocol/initialize-protocol "user-address" cofx-with-ms)
(protocol/initialize-protocol cofx-with-ms "user-address")
[:db :inbox/wnodes])))))))

View File

@ -13,10 +13,10 @@
(deftest receive-whisper-messages-test
(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"
(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"
(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"
(is (:chat-received-message/add-fx actual))))))

View File

@ -12,34 +12,34 @@
:inbox/wnodes {:eth.beta {"mailserver-a" {:sym-key-id sym-key
:address "enode://wnode-id@ip"}}}}})
(defn peers-summary-change-fx-result [sym-key registered-peer? registered-peer-before?]
(inbox/peers-summary-change-fx (if registered-peer-before?
[{:id "wnode-id"}]
[])
(cofx-fixtures sym-key
registered-peer?)))
(defn peers-summary-change-result [sym-key registered-peer? registered-peer-before?]
(inbox/peers-summary-change (cofx-fixtures sym-key
registered-peer?)
(if registered-peer-before?
[{:id "wnode-id"}]
[])))
(deftest peers-summary-change-fx
(deftest peers-summary-change
(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))
#{:status-im.transport.inbox/mark-trusted-peer}))))
(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))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(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))
#{:db :status-im.transport.inbox/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
(is (= (get-in result [:db :mailserver-status])
:connecting))))
(testing "Mailserver 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
@ -101,7 +101,7 @@
(get-in actual [::inbox/request-messages 1 :topics])))))))
(testing "inbox is not ready"
(testing "it does not do anything"
(is (nil? (inbox/request-messages {})))))))
(is (nil? (inbox/request-messages {:db {}})))))))
(deftest request-messages-params
(let [mailserver {:address "peer"
@ -171,14 +171,14 @@
(testing "it sets it to now in seconds"
(is (= 10
(get-in
(inbox/initialize-offline-inbox [] {:now 10000 :db db})
(inbox/initialize-offline-inbox {:now 10000 :db db} [])
[:db :account/account :last-request])))))
(testing "last-request is set"
(testing "leaves it unchanged"
(is (= "sometimeago"
(get-in
(inbox/initialize-offline-inbox
[]
{: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])))))))

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
(testing "handle contact code"
(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"
(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"
(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")))
(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}}}}))))
(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 (= :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]))))

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