[slow sign in] Unlock account's DB before starting node
There is no need to wait for `Statusgo.Login` callback in order to start unlocking realm db: currently it is encrypted via a key which is derived from user’s password, so we can try to unlock that DB before starting node. That’s how password will be checked. Right after that `:home` screen is shown, the node is started, then `Statusgo.Login` executed. The difference in sign in duration is more noticeable on Android devices, where `Statusgo.Login` is much slower because of PFS database encryption.
This commit is contained in:
parent
f6777edbdc
commit
4aa562f6a8
|
@ -391,6 +391,31 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void verify(final String address, final String password, final Callback callback) {
|
||||||
|
Log.d(TAG, "verify");
|
||||||
|
if (!checkAvailability()) {
|
||||||
|
callback.invoke(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Activity currentActivity = getCurrentActivity();
|
||||||
|
|
||||||
|
final String absRootDirPath = currentActivity.getApplicationInfo().dataDir;
|
||||||
|
final String newKeystoreDir = pathCombine(absRootDirPath, "keystore");
|
||||||
|
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String result = Statusgo.VerifyAccountPassword(newKeystoreDir, address, password);
|
||||||
|
|
||||||
|
callback.invoke(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void createAccount(final String password, final Callback callback) {
|
public void createAccount(final String password, final Callback callback) {
|
||||||
Log.d(TAG, "createAccount");
|
Log.d(TAG, "createAccount");
|
||||||
|
|
|
@ -228,6 +228,25 @@ RCT_EXPORT_METHOD(login:(NSString *)address
|
||||||
callback(@[[NSString stringWithUTF8String: result]]);
|
callback(@[[NSString stringWithUTF8String: result]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////// login
|
||||||
|
RCT_EXPORT_METHOD(verify:(NSString *)address
|
||||||
|
password:(NSString *)password
|
||||||
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"VerifyAccountPassword() method called");
|
||||||
|
#endif
|
||||||
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||||
|
NSURL *rootUrl =[[fileManager
|
||||||
|
URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]
|
||||||
|
lastObject];
|
||||||
|
NSURL *absKeystoreUrl = [rootUrl URLByAppendingPathComponent:@"keystore"];
|
||||||
|
|
||||||
|
char * result = VerifyAccountPassword((char *) [absKeystoreUrl.path UTF8String],
|
||||||
|
(char *) [address UTF8String],
|
||||||
|
(char *) [password UTF8String]);
|
||||||
|
callback(@[[NSString stringWithUTF8String: result]]);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
#pragma mark - SendTransaction
|
#pragma mark - SendTransaction
|
||||||
//////////////////////////////////////////////////////////////////// sendTransaction
|
//////////////////////////////////////////////////////////////////// sendTransaction
|
||||||
|
|
|
@ -3,13 +3,17 @@
|
||||||
[status-im.accounts.db :as accounts.db]
|
[status-im.accounts.db :as accounts.db]
|
||||||
[status-im.data-store.core :as data-store]
|
[status-im.data-store.core :as data-store]
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.node.core :as node]
|
|
||||||
[status-im.ui.screens.navigation :as navigation]
|
[status-im.ui.screens.navigation :as navigation]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.utils.keychain.core :as keychain]
|
[status-im.utils.keychain.core :as keychain]
|
||||||
[status-im.utils.types :as types]
|
[status-im.utils.types :as types]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.utils.security :as security]))
|
[status-im.utils.security :as security]
|
||||||
|
[status-im.utils.platform :as platform]
|
||||||
|
[status-im.protocol.core :as protocol]
|
||||||
|
[status-im.models.wallet :as models.wallet]
|
||||||
|
[status-im.models.transactions :as transactions]
|
||||||
|
[status-im.i18n :as i18n]))
|
||||||
|
|
||||||
;; login flow:
|
;; login flow:
|
||||||
;;
|
;;
|
||||||
|
@ -22,13 +26,18 @@
|
||||||
(defn login! [address password save-password?]
|
(defn login! [address password save-password?]
|
||||||
(status/login address password #(re-frame/dispatch [:accounts.login.callback/login-success %])))
|
(status/login address password #(re-frame/dispatch [:accounts.login.callback/login-success %])))
|
||||||
|
|
||||||
|
(defn verify! [address password realm-error]
|
||||||
|
(status/verify address password
|
||||||
|
#(re-frame/dispatch
|
||||||
|
[:accounts.login.callback/verify-success % realm-error])))
|
||||||
|
|
||||||
(defn clear-web-data! []
|
(defn clear-web-data! []
|
||||||
(status/clear-web-data))
|
(status/clear-web-data))
|
||||||
|
|
||||||
(defn change-account! [address password]
|
(defn change-account! [address password create-database-if-not-exist?]
|
||||||
;; No matter what is the keychain we use, as checks are done on decrypting base
|
;; No matter what is the keychain we use, as checks are done on decrypting base
|
||||||
(.. (keychain/safe-get-encryption-key)
|
(.. (keychain/safe-get-encryption-key)
|
||||||
(then #(data-store/change-account address password %))
|
(then #(data-store/change-account address password % create-database-if-not-exist?))
|
||||||
(then (fn [] (re-frame/dispatch [:init.callback/account-change-success address])))
|
(then (fn [] (re-frame/dispatch [:init.callback/account-change-success address])))
|
||||||
(catch (fn [error]
|
(catch (fn [error]
|
||||||
(log/warn "Could not change account" error)
|
(log/warn "Could not change account" error)
|
||||||
|
@ -40,26 +49,137 @@
|
||||||
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
|
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
|
||||||
{:accounts.login/login [address password save-password?]}))
|
{:accounts.login/login [address password save-password?]}))
|
||||||
|
|
||||||
(fx/defn user-login [{:keys [db] :as cofx}]
|
(fx/defn initialize-wallet [cofx]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (assoc-in db [:accounts/login :processing] true)}
|
(models.wallet/initialize-tokens)
|
||||||
(node/initialize (get-in db [:accounts/login :address]))))
|
(models.wallet/update-wallet)
|
||||||
|
(transactions/start-sync)))
|
||||||
|
|
||||||
|
(fx/defn user-login [{:keys [db] :as cofx}]
|
||||||
|
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
|
||||||
|
(fx/merge
|
||||||
|
cofx
|
||||||
|
(merge
|
||||||
|
{:db (assoc-in db [:accounts/login :processing] true)
|
||||||
|
:accounts.login/clear-web-data nil
|
||||||
|
:data-store/change-account [address password false]}
|
||||||
|
(when save-password?
|
||||||
|
{:keychain/save-user-password [address password]})))))
|
||||||
|
|
||||||
|
(fx/defn account-and-db-password-do-not-match
|
||||||
|
[{:keys [db] :as cofx} error]
|
||||||
|
(fx/merge
|
||||||
|
cofx
|
||||||
|
{:db
|
||||||
|
(update db :accounts/login assoc
|
||||||
|
:error error
|
||||||
|
:processing false)
|
||||||
|
|
||||||
|
:utils/show-popup
|
||||||
|
{:title (i18n/label :account-and-db-password-mismatch-title)
|
||||||
|
:content (i18n/label :account-and-db-password-mismatch-content)}
|
||||||
|
|
||||||
|
:dispatch [:accounts.logout.ui/logout-confirmed]}))
|
||||||
|
|
||||||
(fx/defn user-login-callback
|
(fx/defn user-login-callback
|
||||||
[{db :db :as cofx} login-result]
|
[{:keys [db web3] :as cofx} login-result]
|
||||||
(let [data (types/json->clj login-result)
|
(let [data (types/json->clj login-result)
|
||||||
|
error (:error data)
|
||||||
|
success (empty? error)
|
||||||
|
address (get-in db [:account/account :address])]
|
||||||
|
;; check if logged into account
|
||||||
|
(when address
|
||||||
|
(if success
|
||||||
|
(fx/merge
|
||||||
|
cofx
|
||||||
|
{:db (dissoc db :accounts/login)
|
||||||
|
:web3/set-default-account [web3 address]
|
||||||
|
:web3/fetch-node-version [web3
|
||||||
|
#(re-frame/dispatch
|
||||||
|
[:web3/fetch-node-version-callback %])]}
|
||||||
|
(protocol/initialize-protocol address)
|
||||||
|
#(when-not platform/desktop?
|
||||||
|
(initialize-wallet %)))
|
||||||
|
(account-and-db-password-do-not-match cofx error)))))
|
||||||
|
|
||||||
|
(fx/defn show-migration-error-dialog
|
||||||
|
[{:keys [db]} realm-error]
|
||||||
|
(let [{:keys [message]} realm-error
|
||||||
|
address (get-in db [:accounts/login :address])
|
||||||
|
erase-button (i18n/label :migrations-erase-accounts-data-button)]
|
||||||
|
{:ui/show-confirmation
|
||||||
|
{:title (i18n/label :invalid-key-title)
|
||||||
|
:content (i18n/label
|
||||||
|
:invalid-key-content
|
||||||
|
{:message message
|
||||||
|
:erase-accounts-data-button-text erase-button})
|
||||||
|
:confirm-button-text (i18n/label :invalid-key-confirm)
|
||||||
|
:on-cancel #(re-frame/dispatch
|
||||||
|
[:init.ui/data-reset-cancelled ""])
|
||||||
|
:on-accept #(re-frame/dispatch
|
||||||
|
[:init.ui/account-data-reset-accepted address])}}))
|
||||||
|
(fx/defn verify-callback
|
||||||
|
[{:keys [db] :as cofx} verify-result realm-error]
|
||||||
|
(let [data (types/json->clj verify-result)
|
||||||
error (:error data)
|
error (:error data)
|
||||||
success (empty? error)]
|
success (empty? error)]
|
||||||
(if success
|
(if success
|
||||||
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
|
(case (:error realm-error)
|
||||||
(merge {:accounts.login/clear-web-data nil
|
:decryption-failed
|
||||||
:data-store/change-account [address password]}
|
(show-migration-error-dialog cofx realm-error)
|
||||||
(when save-password?
|
|
||||||
{:keychain/save-user-password [address password]})))
|
:database-does-not-exist
|
||||||
|
(let [{:keys [address password]} (accounts.db/credentials cofx)]
|
||||||
|
{:data-store/change-account [address password true]}))
|
||||||
{:db (update db :accounts/login assoc
|
{:db (update db :accounts/login assoc
|
||||||
:error error
|
:error error
|
||||||
:processing false)})))
|
:processing false)})))
|
||||||
|
|
||||||
|
(fx/defn handle-change-account-error
|
||||||
|
[{:keys [db] :as cofx} error]
|
||||||
|
(let [{:keys [error message details] :as realm-error}
|
||||||
|
(if (map? error)
|
||||||
|
error
|
||||||
|
{:message (str error)})
|
||||||
|
{:keys [address password]} (accounts.db/credentials cofx)
|
||||||
|
erase-button (i18n/label :migrations-erase-accounts-data-button)]
|
||||||
|
(case error
|
||||||
|
:migrations-failed
|
||||||
|
(let [{:keys [message]} realm-error
|
||||||
|
address (get-in db [:accounts/login :address])]
|
||||||
|
{:ui/show-confirmation
|
||||||
|
{:title (i18n/label :migrations-failed-title)
|
||||||
|
:content (i18n/label
|
||||||
|
:migrations-failed-content
|
||||||
|
(merge
|
||||||
|
{:message message
|
||||||
|
:erase-accounts-data-button-text erase-button}
|
||||||
|
details))
|
||||||
|
:confirm-button-text erase-button
|
||||||
|
:on-cancel #(re-frame/dispatch
|
||||||
|
[:init.ui/data-reset-cancelled ""])
|
||||||
|
:on-accept #(re-frame/dispatch
|
||||||
|
[:init.ui/account-data-reset-accepted address])}})
|
||||||
|
|
||||||
|
:database-does-not-exist
|
||||||
|
{:accounts.login/verify [address password realm-error]}
|
||||||
|
|
||||||
|
:decryption-failed
|
||||||
|
;; check if decryption failed because of wrong password
|
||||||
|
{:accounts.login/verify [address password realm-error]}
|
||||||
|
|
||||||
|
{:ui/show-confirmation
|
||||||
|
{:title (i18n/label :unknown-realm-error)
|
||||||
|
:content (i18n/label
|
||||||
|
:unknown-realm-error-content
|
||||||
|
{:message message
|
||||||
|
:erase-accounts-data-button-text erase-button})
|
||||||
|
:confirm-button-text (i18n/label :invalid-key-confirm)
|
||||||
|
:on-cancel #(re-frame/dispatch
|
||||||
|
[:init.ui/data-reset-cancelled ""])
|
||||||
|
:on-accept #(re-frame/dispatch
|
||||||
|
[:init.ui/account-data-reset-accepted address])}})))
|
||||||
|
|
||||||
(fx/defn open-login [{:keys [db]} address photo-path name]
|
(fx/defn open-login [{:keys [db]} address photo-path name]
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(update :accounts/login assoc
|
(update :accounts/login assoc
|
||||||
|
@ -87,11 +207,17 @@
|
||||||
(fn [[address password save-password?]]
|
(fn [[address password save-password?]]
|
||||||
(login! address (security/safe-unmask-data password) save-password?)))
|
(login! address (security/safe-unmask-data password) save-password?)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:accounts.login/verify
|
||||||
|
(fn [[address password realm-error]]
|
||||||
|
(verify! address (security/safe-unmask-data password) realm-error)))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:accounts.login/clear-web-data
|
:accounts.login/clear-web-data
|
||||||
clear-web-data!)
|
clear-web-data!)
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:data-store/change-account
|
:data-store/change-account
|
||||||
(fn [[address password]]
|
(fn [[address password create-database-if-not-exist?]]
|
||||||
(change-account! address (security/safe-unmask-data password))))
|
(change-account! address (security/safe-unmask-data password)
|
||||||
|
create-database-if-not-exist?)))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
(ns status-im.accounts.logout.core
|
(ns status-im.accounts.logout.core
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.init.core :as init]
|
|
||||||
[status-im.transport.core :as transport]
|
[status-im.transport.core :as transport]
|
||||||
[status-im.ui.screens.navigation :as navigation]
|
[status-im.ui.screens.navigation :as navigation]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
|
@ -12,11 +11,11 @@
|
||||||
(let [{:transport/keys [chats]} db]
|
(let [{:transport/keys [chats]} db]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:keychain/clear-user-password (get-in db [:account/account :address])
|
{:keychain/clear-user-password (get-in db [:account/account :address])
|
||||||
:dev-server/stop nil}
|
:dev-server/stop nil
|
||||||
|
:keychain/get-encryption-key [:init.callback/get-encryption-key-success]}
|
||||||
(transactions/stop-sync)
|
(transactions/stop-sync)
|
||||||
(navigation/navigate-to-clean :login {})
|
(navigation/navigate-to-clean :login {})
|
||||||
(transport/stop-whisper)
|
(transport/stop-whisper))))
|
||||||
(init/initialize-keychain))))
|
|
||||||
|
|
||||||
(fx/defn show-logout-confirmation [_]
|
(fx/defn show-logout-confirmation [_]
|
||||||
{:ui/show-confirmation
|
{:ui/show-confirmation
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
(log/error "Could not move realms" error)))
|
(log/error "Could not move realms" error)))
|
||||||
(then #(data-source/open-base-realm encryption-key)))))
|
(then #(data-source/open-base-realm encryption-key)))))
|
||||||
|
|
||||||
(defn change-account [address password encryption-key]
|
(defn change-account
|
||||||
|
[address password encryption-key create-database-if-not-exist?]
|
||||||
(log/debug "changing account to: " address)
|
(log/debug "changing account to: " address)
|
||||||
(..
|
(..
|
||||||
(js/Promise.
|
(js/Promise.
|
||||||
|
@ -36,6 +37,10 @@
|
||||||
(catch :default e
|
(catch :default e
|
||||||
(on-error {:message (str e)
|
(on-error {:message (str e)
|
||||||
:error :closing-account-failed})))))
|
:error :closing-account-failed})))))
|
||||||
|
(then
|
||||||
|
(if create-database-if-not-exist?
|
||||||
|
#(js/Promise. (fn [on-success] (on-success)))
|
||||||
|
#(data-source/db-exists? address)))
|
||||||
(then
|
(then
|
||||||
#(data-source/check-db-encryption address password encryption-key))
|
#(data-source/check-db-encryption address password encryption-key))
|
||||||
(then
|
(then
|
||||||
|
|
|
@ -255,6 +255,16 @@
|
||||||
#(re-encrypt-realm file-name old-key new-key on-success on-error))
|
#(re-encrypt-realm file-name old-key new-key on-success on-error))
|
||||||
(catch on-error)))))))))
|
(catch on-error)))))))))
|
||||||
|
|
||||||
|
(defn db-exists? [address]
|
||||||
|
(js/Promise.
|
||||||
|
(fn [on-success on-error]
|
||||||
|
(.. (fs/file-exists? (get-account-db-path address))
|
||||||
|
(then (fn [db-exists?]
|
||||||
|
(if db-exists?
|
||||||
|
(on-success)
|
||||||
|
(on-error {:message "Account's database doesn't exist."
|
||||||
|
:error :database-does-not-exist}))))))))
|
||||||
|
|
||||||
(defn open-account [address password encryption-key]
|
(defn open-account [address password encryption-key]
|
||||||
(let [path (get-account-db-path address)
|
(let [path (get-account-db-path address)
|
||||||
account-db-key (db-encryption-key password encryption-key)]
|
account-db-key (db-encryption-key password encryption-key)]
|
||||||
|
|
|
@ -45,7 +45,8 @@
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.utils.datetime :as time]
|
[status-im.utils.datetime :as time]
|
||||||
[status-im.chat.commands.core :as commands]
|
[status-im.chat.commands.core :as commands]
|
||||||
[status-im.chat.models.loading :as chat-loading]))
|
[status-im.chat.models.loading :as chat-loading]
|
||||||
|
[status-im.node.core :as node]))
|
||||||
|
|
||||||
;; init module
|
;; init module
|
||||||
|
|
||||||
|
@ -102,15 +103,11 @@
|
||||||
:init-chats
|
:init-chats
|
||||||
[(re-frame/inject-cofx :web3/get-web3)
|
[(re-frame/inject-cofx :web3/get-web3)
|
||||||
(re-frame/inject-cofx :get-default-dapps)
|
(re-frame/inject-cofx :get-default-dapps)
|
||||||
(re-frame/inject-cofx :data-store/all-chats)
|
(re-frame/inject-cofx :data-store/all-chats)]
|
||||||
(re-frame/inject-cofx :data-store/get-all-mailservers)
|
|
||||||
(re-frame/inject-cofx :data-store/transport)
|
|
||||||
(re-frame/inject-cofx :data-store/mailserver-topics)]
|
|
||||||
(fn [{:keys [db] :as cofx} [_ address]]
|
(fn [{:keys [db] :as cofx} [_ address]]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (assoc db :chats/loading? false)}
|
{:db (assoc db :chats/loading? false)}
|
||||||
(chat-loading/initialize-chats)
|
(chat-loading/initialize-chats)
|
||||||
(protocol/initialize-protocol address)
|
|
||||||
(chat-loading/initialize-pending-messages))))
|
(chat-loading/initialize-pending-messages))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
|
@ -120,13 +117,11 @@
|
||||||
(re-frame/inject-cofx :data-store/get-all-installations)
|
(re-frame/inject-cofx :data-store/get-all-installations)
|
||||||
(re-frame/inject-cofx :data-store/all-browsers)
|
(re-frame/inject-cofx :data-store/all-browsers)
|
||||||
(re-frame/inject-cofx :data-store/all-dapp-permissions)]
|
(re-frame/inject-cofx :data-store/all-dapp-permissions)]
|
||||||
(fn [cofx [_ address]]
|
(fn [{:keys [db] :as cofx} [_ address]]
|
||||||
(init/initialize-account cofx address)))
|
(fx/merge
|
||||||
|
cofx
|
||||||
(handlers/register-handler-fx
|
(node/initialize (get-in db [:accounts/login :address]))
|
||||||
:init.callback/account-change-error
|
(init/initialize-account address))))
|
||||||
(fn [cofx [_ error]]
|
|
||||||
(init/handle-change-account-error cofx error)))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:init.callback/keychain-reset
|
:init.callback/keychain-reset
|
||||||
|
@ -261,9 +256,24 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:accounts.login.callback/login-success
|
:accounts.login.callback/login-success
|
||||||
|
[(re-frame/inject-cofx :web3/get-web3)
|
||||||
|
(re-frame/inject-cofx :data-store/all-chats)
|
||||||
|
(re-frame/inject-cofx :data-store/get-all-mailservers)
|
||||||
|
(re-frame/inject-cofx :data-store/transport)
|
||||||
|
(re-frame/inject-cofx :data-store/mailserver-topics)]
|
||||||
(fn [cofx [_ login-result]]
|
(fn [cofx [_ login-result]]
|
||||||
(accounts.login/user-login-callback cofx login-result)))
|
(accounts.login/user-login-callback cofx login-result)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:accounts.login.callback/verify-success
|
||||||
|
(fn [cofx [_ verify-result realm-error]]
|
||||||
|
(accounts.login/verify-callback cofx verify-result realm-error)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:init.callback/account-change-error
|
||||||
|
(fn [cofx [_ error]]
|
||||||
|
(accounts.login/handle-change-account-error cofx error)))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:accounts.login.ui/account-selected
|
:accounts.login.ui/account-selected
|
||||||
(fn [cofx [_ address photo-path name]]
|
(fn [cofx [_ address photo-path name]]
|
||||||
|
|
|
@ -106,41 +106,6 @@
|
||||||
[{:keys [db]} device-uuid]
|
[{:keys [db]} device-uuid]
|
||||||
{:db (assoc db :device-UUID device-uuid)})
|
{:db (assoc db :device-UUID device-uuid)})
|
||||||
|
|
||||||
(fx/defn handle-change-account-error
|
|
||||||
[{:keys [db]} error]
|
|
||||||
(let [{:keys [error message details]}
|
|
||||||
(if (map? error)
|
|
||||||
error
|
|
||||||
{:message (str error)})
|
|
||||||
address (get-in db [:accounts/login :address])
|
|
||||||
erase-button-text (i18n/label :migrations-erase-accounts-data-button)]
|
|
||||||
(case error
|
|
||||||
:migrations-failed
|
|
||||||
{:ui/show-confirmation
|
|
||||||
{:title (i18n/label :migrations-failed-title)
|
|
||||||
:content (i18n/label
|
|
||||||
:migrations-failed-content
|
|
||||||
(merge
|
|
||||||
{:message message
|
|
||||||
:erase-accounts-data-button-text erase-button-text}
|
|
||||||
details))
|
|
||||||
:confirm-button-text erase-button-text
|
|
||||||
:on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""])
|
|
||||||
:on-accept #(re-frame/dispatch [:init.ui/account-data-reset-accepted address])}}
|
|
||||||
|
|
||||||
;; TODO(rasom): handle different errors as separate cases
|
|
||||||
;; Right now it might be corrupted db file, wrong password,
|
|
||||||
;; problem with permissions, etc.
|
|
||||||
{:ui/show-confirmation
|
|
||||||
{:title (i18n/label :invalid-key-title)
|
|
||||||
:content (i18n/label
|
|
||||||
:invalid-key-content
|
|
||||||
{:message message
|
|
||||||
:erase-accounts-data-button-text erase-button-text})
|
|
||||||
:confirm-button-text (i18n/label :invalid-key-confirm)
|
|
||||||
:on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""])
|
|
||||||
:on-accept #(re-frame/dispatch [:init.ui/account-data-reset-accepted address])}})))
|
|
||||||
|
|
||||||
(fx/defn handle-init-store-error
|
(fx/defn handle-init-store-error
|
||||||
[encryption-key cofx]
|
[encryption-key cofx]
|
||||||
{:ui/show-confirmation
|
{:ui/show-confirmation
|
||||||
|
@ -183,9 +148,9 @@
|
||||||
|
|
||||||
(fx/defn initialize-account-db [{:keys [db web3]} address]
|
(fx/defn initialize-account-db [{:keys [db web3]} address]
|
||||||
(let [{:universal-links/keys [url]
|
(let [{:universal-links/keys [url]
|
||||||
:keys [accounts/accounts accounts/create contacts/contacts networks/networks
|
:keys [accounts/accounts accounts/create networks/networks network
|
||||||
network network-status peers-count peers-summary view-id navigation-stack
|
network-status peers-count peers-summary view-id navigation-stack
|
||||||
pairing/installations status-module-initialized? device-UUID semaphores]
|
status-module-initialized? device-UUID semaphores accounts/login]
|
||||||
:node/keys [status]
|
:node/keys [status]
|
||||||
:or {network (get app-db :network)}} db
|
:or {network (get app-db :network)}} db
|
||||||
current-account (get accounts address)
|
current-account (get accounts address)
|
||||||
|
@ -199,6 +164,8 @@
|
||||||
:accounts/create create
|
:accounts/create create
|
||||||
:networks/networks networks
|
:networks/networks networks
|
||||||
:account/account current-account
|
:account/account current-account
|
||||||
|
:accounts/login login
|
||||||
|
:accounts/accounts accounts
|
||||||
:network-status network-status
|
:network-status network-status
|
||||||
:network network
|
:network network
|
||||||
:chain (ethereum/network->chain-name account-network)
|
:chain (ethereum/network->chain-name account-network)
|
||||||
|
@ -211,12 +178,6 @@
|
||||||
(= view-id :create-account)
|
(= view-id :create-account)
|
||||||
(assoc-in [:accounts/create :step] :enter-name))}))
|
(assoc-in [:accounts/create :step] :enter-name))}))
|
||||||
|
|
||||||
(defn initialize-wallet [cofx]
|
|
||||||
(fx/merge cofx
|
|
||||||
(models.wallet/initialize-tokens)
|
|
||||||
(models.wallet/update-wallet)
|
|
||||||
(transactions/start-sync)))
|
|
||||||
|
|
||||||
(defn login-only-events [cofx address]
|
(defn login-only-events [cofx address]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:notifications/request-notifications-permissions nil}
|
{:notifications/request-notifications-permissions nil}
|
||||||
|
@ -234,23 +195,18 @@
|
||||||
(= (get-in cofx [:db :view-id])
|
(= (get-in cofx [:db :view-id])
|
||||||
:create-account))
|
:create-account))
|
||||||
|
|
||||||
(fx/defn initialize-account [{:keys [db web3] :as cofx} address]
|
(fx/defn initialize-account [cofx address]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:web3/set-default-account [web3 address]
|
{:notifications/get-fcm-token nil}
|
||||||
:web3/fetch-node-version [web3
|
|
||||||
#(re-frame/dispatch
|
|
||||||
[:web3/fetch-node-version-callback %])]
|
|
||||||
:notifications/get-fcm-token nil}
|
|
||||||
(initialize-account-db address)
|
(initialize-account-db address)
|
||||||
(contact/load-contacts)
|
(contact/load-contacts)
|
||||||
(pairing/load-installations)
|
(pairing/load-installations)
|
||||||
#(when (dev-mode? %)
|
#(when (dev-mode? %)
|
||||||
(models.dev-server/start))
|
(models.dev-server/start))
|
||||||
(browser/initialize-browsers)
|
(browser/initialize-browsers)
|
||||||
|
|
||||||
(browser/initialize-dapp-permissions)
|
(browser/initialize-dapp-permissions)
|
||||||
(extensions.registry/initialize)
|
(extensions.registry/initialize)
|
||||||
#(when-not platform/desktop?
|
|
||||||
(initialize-wallet %))
|
|
||||||
(accounts.update/update-sign-in-time)
|
(accounts.update/update-sign-in-time)
|
||||||
#(when-not (creating-account? %)
|
#(when-not (creating-account? %)
|
||||||
(login-only-events % address))))
|
(login-only-events % address))))
|
||||||
|
|
|
@ -365,12 +365,13 @@
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
;; check if logged into account
|
;; check if logged into account
|
||||||
(when (contains? db :account/account)
|
(when (contains? db :account/account)
|
||||||
(if (zero? (dec (:mailserver/connection-checks db)))
|
(let [connection-checks (dec (:mailserver/connection-checks db))]
|
||||||
(fx/merge cofx
|
(if (>= 0 connection-checks)
|
||||||
{:db (dissoc db :mailserver/connection-checks)}
|
(fx/merge cofx
|
||||||
(when (= :connecting (:mailserver/state db))
|
{:db (dissoc db :mailserver/connection-checks)}
|
||||||
(change-mailserver cofx)))
|
(when (= :connecting (:mailserver/state db))
|
||||||
{:db (update db :mailserver/connection-checks dec)})))
|
(change-mailserver cofx)))
|
||||||
|
{:db (update db :mailserver/connection-checks dec)}))))
|
||||||
|
|
||||||
(fx/defn reset-request-to
|
(fx/defn reset-request-to
|
||||||
[{:keys [db]}]
|
[{:keys [db]}]
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
(defn start-node [config]
|
(defn start-node [config]
|
||||||
(native-module/start-node config))
|
(native-module/start-node config))
|
||||||
|
|
||||||
|
(defn node-ready []
|
||||||
|
(native-module/node-ready))
|
||||||
|
|
||||||
(defn stop-node []
|
(defn stop-node []
|
||||||
(native-module/stop-node))
|
(native-module/stop-node))
|
||||||
|
|
||||||
|
@ -18,6 +21,9 @@
|
||||||
(defn login [address password callback]
|
(defn login [address password callback]
|
||||||
(native-module/login address password callback))
|
(native-module/login address password callback))
|
||||||
|
|
||||||
|
(defn verify [address password callback]
|
||||||
|
(native-module/verify address password callback))
|
||||||
|
|
||||||
(defn set-soft-input-mode [mode]
|
(defn set-soft-input-mode [mode]
|
||||||
(native-module/set-soft-input-mode mode))
|
(native-module/set-soft-input-mode mode))
|
||||||
|
|
||||||
|
|
|
@ -54,10 +54,16 @@
|
||||||
(.addListener r/device-event-emitter "gethEvent"
|
(.addListener r/device-event-emitter "gethEvent"
|
||||||
#(re-frame/dispatch [:signals/signal-received (.-jsonEvent %)])))
|
#(re-frame/dispatch [:signals/signal-received (.-jsonEvent %)])))
|
||||||
|
|
||||||
|
(defonce node-started (atom false))
|
||||||
|
|
||||||
(defn stop-node []
|
(defn stop-node []
|
||||||
|
(reset! node-started false)
|
||||||
(when status
|
(when status
|
||||||
(call-module #(.stopNode status))))
|
(call-module #(.stopNode status))))
|
||||||
|
|
||||||
|
(defn node-ready []
|
||||||
|
(reset! node-started true))
|
||||||
|
|
||||||
(defn start-node [config]
|
(defn start-node [config]
|
||||||
(when status
|
(when status
|
||||||
(call-module #(.startNode status config))))
|
(call-module #(.startNode status config))))
|
||||||
|
@ -82,17 +88,21 @@
|
||||||
(call-module #(.notifyUsers status message payload tokens on-result))))
|
(call-module #(.notifyUsers status message payload tokens on-result))))
|
||||||
|
|
||||||
(defn add-peer [enode on-result]
|
(defn add-peer [enode on-result]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.addPeer status enode on-result))))
|
(call-module #(.addPeer status enode on-result))))
|
||||||
|
|
||||||
(defn recover-account [passphrase password on-result]
|
(defn recover-account [passphrase password on-result]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.recoverAccount status passphrase password on-result))))
|
(call-module #(.recoverAccount status passphrase password on-result))))
|
||||||
|
|
||||||
(defn login [address password on-result]
|
(defn login [address password on-result]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.login status address password on-result))))
|
(call-module #(.login status address password on-result))))
|
||||||
|
|
||||||
|
(defn verify [address password on-result]
|
||||||
|
(when (and @node-started status)
|
||||||
|
(call-module #(.verify status address password on-result))))
|
||||||
|
|
||||||
(defn set-soft-input-mode [mode]
|
(defn set-soft-input-mode [mode]
|
||||||
(when status
|
(when status
|
||||||
(call-module #(.setSoftInputMode status mode))))
|
(call-module #(.setSoftInputMode status mode))))
|
||||||
|
@ -103,19 +113,19 @@
|
||||||
(call-module #(.clearStorageAPIs status))))
|
(call-module #(.clearStorageAPIs status))))
|
||||||
|
|
||||||
(defn call-rpc [payload callback]
|
(defn call-rpc [payload callback]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.callRPC status payload callback))))
|
(call-module #(.callRPC status payload callback))))
|
||||||
|
|
||||||
(defn call-private-rpc [payload callback]
|
(defn call-private-rpc [payload callback]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.callPrivateRPC status payload callback))))
|
(call-module #(.callPrivateRPC status payload callback))))
|
||||||
|
|
||||||
(defn sign-message [rpcParams callback]
|
(defn sign-message [rpcParams callback]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.signMessage status rpcParams callback))))
|
(call-module #(.signMessage status rpcParams callback))))
|
||||||
|
|
||||||
(defn send-transaction [rpcParams password callback]
|
(defn send-transaction [rpcParams password callback]
|
||||||
(when status
|
(when (and @node-started status)
|
||||||
(call-module #(.sendTransaction status rpcParams password callback))))
|
(call-module #(.sendTransaction status rpcParams password callback))))
|
||||||
|
|
||||||
(defn close-application []
|
(defn close-application []
|
||||||
|
|
|
@ -177,6 +177,11 @@
|
||||||
(fn [config]
|
(fn [config]
|
||||||
(status/start-node config)))
|
(status/start-node config)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:node/ready
|
||||||
|
(fn [config]
|
||||||
|
(status/node-ready)))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:node/stop
|
:node/stop
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
[status-im.react-native.js-dependencies :as rn]
|
[status-im.react-native.js-dependencies :as rn]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.accounts.db :as accounts.db]
|
[status-im.accounts.db :as accounts.db]
|
||||||
[status-im.accounts.login.core :as accounts.login]
|
|
||||||
[status-im.chat.models :as chat-model]
|
[status-im.chat.models :as chat-model]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.utils.fx :as fx]))
|
[status-im.utils.fx :as fx]))
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
can-login? (and (not restart?)
|
can-login? (and (not restart?)
|
||||||
(:password (accounts.db/credentials cofx)))]
|
(:password (accounts.db/credentials cofx)))]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc :node/status :started)
|
(assoc :node/status :started)
|
||||||
(dissoc :node/restart? :node/address))}
|
(dissoc :node/restart? :node/address))
|
||||||
|
:node/ready nil}
|
||||||
|
|
||||||
(when restart?
|
(when restart?
|
||||||
(node/initialize address))
|
(node/initialize address))
|
||||||
|
|
|
@ -38,7 +38,9 @@
|
||||||
(string/starts-with? error "there is no running node")
|
(string/starts-with? error "there is no running node")
|
||||||
:t/node-unavailable
|
:t/node-unavailable
|
||||||
|
|
||||||
(string/starts-with? error "cannot retrieve a valid key")
|
(or
|
||||||
|
(string/starts-with? error "cannot retrieve a valid key")
|
||||||
|
(string/starts-with? error "could not decrypt key"))
|
||||||
:t/wrong-password
|
:t/wrong-password
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
|
|
@ -14,20 +14,22 @@
|
||||||
(animation/timing spin-value {:toValue to-spin-value
|
(animation/timing spin-value {:toValue to-spin-value
|
||||||
:duration 300})))))
|
:duration 300})))))
|
||||||
|
|
||||||
(defn sendable? [input-text offline?]
|
(defn sendable? [input-text offline? login-processing?]
|
||||||
(let [trimmed (string/trim input-text)]
|
(let [trimmed (string/trim input-text)]
|
||||||
(not (or (string/blank? trimmed)
|
(not (or (string/blank? trimmed)
|
||||||
(= trimmed "/")
|
(= trimmed "/")
|
||||||
offline?))))
|
offline?
|
||||||
|
login-processing?))))
|
||||||
|
|
||||||
(defview send-button-view []
|
(defview send-button-view []
|
||||||
(letsubs [{:keys [command-completion]} [:chats/selected-chat-command]
|
(letsubs [{:keys [command-completion]} [:chats/selected-chat-command]
|
||||||
{:keys [input-text seq-arg-input-text]} [:chats/current-chat]
|
{:keys [input-text]} [:chats/current-chat]
|
||||||
offline? [:offline?]
|
offline? [:offline?]
|
||||||
spin-value (animation/create-value 1)]
|
spin-value (animation/create-value 1)
|
||||||
|
login-processing? [:get-in [:accounts/login :processing]]]
|
||||||
{:component-did-update (send-button-view-on-update {:spin-value spin-value
|
{:component-did-update (send-button-view-on-update {:spin-value spin-value
|
||||||
:command-completion command-completion})}
|
:command-completion command-completion})}
|
||||||
(when (and (sendable? input-text offline?)
|
(when (and (sendable? input-text offline? login-processing?)
|
||||||
(or (not command-completion)
|
(or (not command-completion)
|
||||||
(#{:complete :less-than-needed} command-completion)))
|
(#{:complete :less-than-needed} command-completion)))
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/send-current-message])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/send-current-message])}
|
||||||
|
|
|
@ -72,6 +72,9 @@
|
||||||
(def settings-item-destructive
|
(def settings-item-destructive
|
||||||
{:color colors/red})
|
{:color colors/red})
|
||||||
|
|
||||||
|
(def settings-item-disabled
|
||||||
|
{:color colors/gray})
|
||||||
|
|
||||||
(def settings-item-value
|
(def settings-item-value
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:flex-wrap :nowrap
|
:flex-wrap :nowrap
|
||||||
|
|
|
@ -84,7 +84,8 @@
|
||||||
[react/view styles/settings-item
|
[react/view styles/settings-item
|
||||||
[react/view styles/settings-item-text-wrapper
|
[react/view styles/settings-item-text-wrapper
|
||||||
[react/text {:style (merge styles/settings-item-text
|
[react/text {:style (merge styles/settings-item-text
|
||||||
(when destructive? styles/settings-item-destructive))
|
(when destructive? styles/settings-item-destructive)
|
||||||
|
(when-not active? styles/settings-item-disabled))
|
||||||
:number-of-lines 1}
|
:number-of-lines 1}
|
||||||
(or item-text (i18n/label label-kw))]
|
(or item-text (i18n/label label-kw))]
|
||||||
(when-not (string/blank? value)
|
(when-not (string/blank? value)
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
:source source
|
:source source
|
||||||
:value value}]))
|
:value value}]))
|
||||||
|
|
||||||
(defn- my-profile-settings [{:keys [seed-backed-up? mnemonic]} {:keys [settings]} currency]
|
(defn- my-profile-settings [{:keys [seed-backed-up? mnemonic]} {:keys [settings]} currency logged-in?]
|
||||||
(let [show-backup-seed? (and (not seed-backed-up?) (not (string/blank? mnemonic)))]
|
(let [show-backup-seed? (and (not seed-backed-up?) (not (string/blank? mnemonic)))]
|
||||||
[react/view
|
[react/view
|
||||||
[profile.components/settings-title (i18n/label :t/settings)]
|
[profile.components/settings-title (i18n/label :t/settings)]
|
||||||
|
@ -143,6 +143,7 @@
|
||||||
:accessibility-label :log-out-button
|
:accessibility-label :log-out-button
|
||||||
:destructive? true
|
:destructive? true
|
||||||
:hide-arrow? true
|
:hide-arrow? true
|
||||||
|
:active? logged-in?
|
||||||
:action-fn #(re-frame/dispatch [:accounts.logout.ui/logout-pressed])}]]]]))
|
:action-fn #(re-frame/dispatch [:accounts.logout.ui/logout-pressed])}]]]]))
|
||||||
|
|
||||||
(defview advanced-settings [{:keys [network networks dev-mode? settings]} on-show]
|
(defview advanced-settings [{:keys [network networks dev-mode? settings]} on-show]
|
||||||
|
@ -214,6 +215,7 @@
|
||||||
editing? [:get :my-profile/editing?]
|
editing? [:get :my-profile/editing?]
|
||||||
changed-account [:get :my-profile/profile]
|
changed-account [:get :my-profile/profile]
|
||||||
currency [:wallet/currency]
|
currency [:wallet/currency]
|
||||||
|
login-data [:get :accounts/login]
|
||||||
scroll (reagent/atom nil)]
|
scroll (reagent/atom nil)]
|
||||||
(let [shown-account (merge current-account changed-account)
|
(let [shown-account (merge current-account changed-account)
|
||||||
;; We scroll on the component once rendered. setTimeout is necessary,
|
;; We scroll on the component once rendered. setTimeout is necessary,
|
||||||
|
@ -252,5 +254,5 @@
|
||||||
:accessibility-label :share-my-profile-button}
|
:accessibility-label :share-my-profile-button}
|
||||||
(i18n/label :t/share-my-profile)]]
|
(i18n/label :t/share-my-profile)]]
|
||||||
[react/view styles/my-profile-info-container
|
[react/view styles/my-profile-info-container
|
||||||
[my-profile-settings current-account shown-account currency]]
|
[my-profile-settings current-account shown-account currency (nil? login-data)]]
|
||||||
[advanced shown-account on-show-advanced]]])))
|
[advanced shown-account on-show-advanced]]])))
|
||||||
|
|
|
@ -17,3 +17,6 @@
|
||||||
|
|
||||||
(defn unlink [path]
|
(defn unlink [path]
|
||||||
(.unlink rn-dependencies/fs path))
|
(.unlink rn-dependencies/fs path))
|
||||||
|
|
||||||
|
(defn file-exists? [path]
|
||||||
|
(.exists rn-dependencies/fs path))
|
||||||
|
|
|
@ -385,6 +385,7 @@
|
||||||
"currency-display-name-ron": "Romania Leu",
|
"currency-display-name-ron": "Romania Leu",
|
||||||
"log-level-settings": "Log level settings",
|
"log-level-settings": "Log level settings",
|
||||||
"invalid-key-content": "{{message}}\n\nAccount's database can't be encrypted because file is corrupted. There is no way to restore it. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.",
|
"invalid-key-content": "{{message}}\n\nAccount's database can't be encrypted because file is corrupted. There is no way to restore it. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.",
|
||||||
|
"unknown-realm-error-content": "{{message}}\n\nAccount's database can't be opened. Please let us know about this problem at #status public chat. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.",
|
||||||
"advanced-settings": "Advanced settings",
|
"advanced-settings": "Advanced settings",
|
||||||
"group-info": "Group info",
|
"group-info": "Group info",
|
||||||
"currency-display-name-nio": "Nicaragua Cordoba",
|
"currency-display-name-nio": "Nicaragua Cordoba",
|
||||||
|
@ -420,6 +421,7 @@
|
||||||
"wallet-send": "Send",
|
"wallet-send": "Send",
|
||||||
"wallet-deposit": "Deposit",
|
"wallet-deposit": "Deposit",
|
||||||
"invalid-key-title": "We detected a problem with the encryption key",
|
"invalid-key-title": "We detected a problem with the encryption key",
|
||||||
|
"unknown-realm-error": "Something went wrong",
|
||||||
"notifications": "Notifications",
|
"notifications": "Notifications",
|
||||||
"currency-display-name-czk": "Czech Koruna",
|
"currency-display-name-czk": "Czech Koruna",
|
||||||
"extension-installed": "You installed an extension",
|
"extension-installed": "You installed an extension",
|
||||||
|
@ -791,5 +793,7 @@
|
||||||
"install-the-extension": "install the extension",
|
"install-the-extension": "install the extension",
|
||||||
"migrations-failed-title": "Migration failed",
|
"migrations-failed-title": "Migration failed",
|
||||||
"migrations-failed-content": "{{message}}\nschema version: initial {{initial-version}}, current {{current-version}}, last {{last-version}}\n\nPlease let us know about this problem at #status public chat. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.",
|
"migrations-failed-content": "{{message}}\nschema version: initial {{initial-version}}, current {{current-version}}, last {{last-version}}\n\nPlease let us know about this problem at #status public chat. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.",
|
||||||
"migrations-erase-accounts-data-button": "Erase account's db"
|
"migrations-erase-accounts-data-button": "Erase account's db",
|
||||||
|
"account-and-db-password-mismatch-title": "The problem occurred!",
|
||||||
|
"account-and-db-password-mismatch-content": "Account's and realm db passwords do not match."
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue