From 81a865a651da38a0624b9b3c1e896e92dd743812 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Sat, 27 Aug 2016 14:27:48 +0300 Subject: [PATCH] added recover screen and updated bindings Former-commit-id: 9231ab668a1439e46514521ec3b4a6fbab100ea5 --- android/app/build.gradle | 2 +- .../com/statusim/geth/module/GethModule.java | 58 +++++---- .../statusim/geth/service/GethConnector.java | 18 ++- .../statusim/geth/service/GethMessages.java | 10 ++ .../statusim/geth/service/GethService.java | 28 ++++- src/status_im/accounts/handlers.cljs | 46 ++------ src/status_im/accounts/login/handlers.cljs | 53 ++++++++- src/status_im/accounts/login/screen.cljs | 8 -- src/status_im/accounts/login/styles.cljs | 14 --- src/status_im/accounts/recover/handlers.cljs | 37 ++++++ src/status_im/accounts/recover/screen.cljs | 111 ++++++++++++++++++ src/status_im/accounts/recover/styles.cljs | 71 +++++++++++ .../accounts/recover/validations.cljs | 8 ++ src/status_im/accounts/screen.cljs | 30 +++-- src/status_im/accounts/styles.cljs | 28 ++++- src/status_im/android/core.cljs | 9 +- src/status_im/chat/handlers.cljs | 26 +++- src/status_im/chat/sign_up.cljs | 71 +++++------ src/status_im/components/geth.cljs | 8 +- src/status_im/components/styles.cljs | 3 + src/status_im/transactions/handlers.cljs | 28 ++--- src/status_im/translations/en.cljs | 15 ++- 22 files changed, 513 insertions(+), 169 deletions(-) create mode 100644 src/status_im/accounts/recover/handlers.cljs create mode 100644 src/status_im/accounts/recover/screen.cljs create mode 100644 src/status_im/accounts/recover/styles.cljs create mode 100644 src/status_im/accounts/recover/validations.cljs diff --git a/android/app/build.gradle b/android/app/build.gradle index 32424dea01..9f35cceaba 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -139,7 +139,7 @@ dependencies { compile project(':react-native-image-crop-picker') compile project(':react-native-webview-bridge') //compile(name:'statusgo-android-16', ext:'aar') - compile(group: 'status-im', name: 'status-go', version: 'unlock', ext: 'aar') + compile(group: 'status-im', name: 'status-go', version: '0.1.0-574f67', ext: 'aar') compile fileTree(dir: "node_modules/realm/android/libs", include: ["*.jar"]) } diff --git a/android/app/src/main/java/com/statusim/geth/module/GethModule.java b/android/app/src/main/java/com/statusim/geth/module/GethModule.java index 2263f829cd..9ef4326521 100644 --- a/android/app/src/main/java/com/statusim/geth/module/GethModule.java +++ b/android/app/src/main/java/com/statusim/geth/module/GethModule.java @@ -20,11 +20,7 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis private GethConnector geth = null; - private HashMap startNodeCallbacks = new HashMap<>(); - private HashMap createAccountCallbacks = new HashMap<>(); - private HashMap unlockAccountCallbacks = new HashMap<>(); - private HashMap transactionCallbacks = new HashMap<>(); - + private HashMap callbacks = new HashMap<>(); GethModule(ReactApplicationContext reactContext) { super(reactContext); @@ -83,33 +79,34 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis Bundle data = message.getData(); String callbackIdentifier = data.getString(GethConnector.CALLBACK_IDENTIFIER); Log.d(TAG, "callback identifier: " + callbackIdentifier); - Callback callback; + Callback callback = callbacks.remove(callbackIdentifier); + if (callback == null) { + Log.d(TAG, "Could not find callback: " + callbackIdentifier); + } switch (message.what) { case GethMessages.MSG_NODE_STARTED: - Log.d(TAG, "handle startNodeCallbacks size: " + startNodeCallbacks.size()); - callback = startNodeCallbacks.remove(callbackIdentifier); if (callback != null) { callback.invoke(true); - } else { - Log.d(TAG, "Could not find callback: " + callbackIdentifier); } break; case GethMessages.MSG_NODE_STOPPED: break; case GethMessages.MSG_ACCOUNT_CREATED: - callback = createAccountCallbacks.remove(callbackIdentifier); + if (callback != null) { + callback.invoke(data.getString("data")); + } + break; + case GethMessages.MSG_ACCOUNT_RECOVERED: if (callback != null) { callback.invoke(data.getString("data")); } break; case GethMessages.MSG_LOGGED_IN: - callback = unlockAccountCallbacks.remove(callbackIdentifier); if (callback != null) { callback.invoke(data.getString("result")); } break; case GethMessages.MSG_TRANSACTION_COMPLETED: - callback = transactionCallbacks.remove(callbackIdentifier); String result = data.getString("result"); Log.d(TAG, "Send result: " + result + (callback == null)); if (callback != null) { @@ -144,9 +141,7 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis } String callbackIdentifier = createIdentifier(); - Log.d(TAG, "Created callback identifier: " + callbackIdentifier); - startNodeCallbacks.put(callbackIdentifier, callback); - Log.d(TAG, "startNodeCallbacks size: " + startNodeCallbacks.size()); + callbacks.put(callbackIdentifier, callback); geth.startNode(callbackIdentifier); } @@ -167,7 +162,7 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis } String callbackIdentifier = createIdentifier(); - unlockAccountCallbacks.put(callbackIdentifier, callback); + callbacks.put(callbackIdentifier, callback); geth.login(callbackIdentifier, address, password); } @@ -188,17 +183,38 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis } String callbackIdentifier = createIdentifier(); - createAccountCallbacks.put(callbackIdentifier, callback); + callbacks.put(callbackIdentifier, callback); geth.createAccount(callbackIdentifier, password); } + @ReactMethod + public void recoverAccount(String passphrase, String password, Callback callback) { + + Activity currentActivity = getCurrentActivity(); + + if (currentActivity == null) { + callback.invoke("Activity doesn't exist"); + return; + } + + if (geth == null) { + callback.invoke("Geth connector is null"); + return; + } + + String callbackIdentifier = createIdentifier(); + callbacks.put(callbackIdentifier, callback); + + geth.recoverAccount(callbackIdentifier, passphrase, password); + } + private String createIdentifier() { return UUID.randomUUID().toString(); } @ReactMethod - public void completeTransaction(String hash, Callback callback) { + public void completeTransaction(String hash, String password, Callback callback) { Activity currentActivity = getCurrentActivity(); if (currentActivity == null) { @@ -213,9 +229,9 @@ class GethModule extends ReactContextBaseJavaModule implements LifecycleEventLis Log.d(TAG, "Complete transaction: " + hash); String callbackIdentifier = createIdentifier(); - transactionCallbacks.put(callbackIdentifier, callback); + callbacks.put(callbackIdentifier, callback); - geth.completeTransaction(callbackIdentifier, hash); + geth.completeTransaction(callbackIdentifier, hash, password); } private static Callback signalEventCallback; diff --git a/android/app/src/main/java/com/statusim/geth/service/GethConnector.java b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java index 4751064e13..1a90b53e55 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethConnector.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethConnector.java @@ -71,10 +71,26 @@ public class GethConnector extends ServiceConnector { } } - public void completeTransaction(String callbackIdentifier, String hash){ + public void recoverAccount(String callbackIdentifier, String passphrase, String password) { + + if (checkBound()) { + Bundle data = new Bundle(); + data.putString("passphrase", passphrase); + data.putString("password", password); + Message msg = createMessage(callbackIdentifier, GethMessages.MSG_RECOVER_ACCOUNT, data); + try { + serviceMessenger.send(msg); + } catch (RemoteException e) { + Log.e(TAG, "Exception sending message(recoverAccount) to service: ", e); + } + } + } + + public void completeTransaction(String callbackIdentifier, String hash, String password){ if (checkBound()) { Bundle data = new Bundle(); data.putString("hash", hash); + data.putString("password", password); Message msg = createMessage(callbackIdentifier, GethMessages.MSG_COMPLETE_TRANSACTION, data); try { serviceMessenger.send(msg); diff --git a/android/app/src/main/java/com/statusim/geth/service/GethMessages.java b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java index 017bf5cbff..a87c7cb86e 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethMessages.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethMessages.java @@ -43,6 +43,16 @@ public class GethMessages { */ public static final int MSG_ACCOUNT_CREATED = 8; + /** + * Create an account + */ + static final int MSG_RECOVER_ACCOUNT = 9; + + /** + * Account created event + */ + public static final int MSG_ACCOUNT_RECOVERED = 10; + /** * Account complete transaction event */ diff --git a/android/app/src/main/java/com/statusim/geth/service/GethService.java b/android/app/src/main/java/com/statusim/geth/service/GethService.java index b72f73fe58..b444ca6b93 100644 --- a/android/app/src/main/java/com/statusim/geth/service/GethService.java +++ b/android/app/src/main/java/com/statusim/geth/service/GethService.java @@ -95,6 +95,10 @@ public class GethService extends Service { createAccount(message); break; + case GethMessages.MSG_RECOVER_ACCOUNT: + recoverAccount(message); + break; + case GethMessages.MSG_LOGIN: login(message); break; @@ -194,8 +198,7 @@ public class GethService extends Service { private void createAccount(Message message) { Bundle data = message.getData(); String password = data.getString("password"); - // TODO: remove second argument - Log.d(TAG, "Creating account: " + password + " - " + dataFolder); + Log.d(TAG, "Creating account: " + password); String jsonData = Statusgo.CreateAccount(password); Log.d(TAG, "Created account: " + jsonData); @@ -204,13 +207,25 @@ public class GethService extends Service { createAndSendReply(message, GethMessages.MSG_ACCOUNT_CREATED, replyData); } + private void recoverAccount(Message message) { + Bundle data = message.getData(); + String passphrase = data.getString("passphrase"); + String password = data.getString("password"); + Log.d(TAG, "Recovering account: " + passphrase + " - " + password); + String jsonData = Statusgo.RecoverAccount(password, passphrase); + Log.d(TAG, "Recovered account: " + jsonData); + + Bundle replyData = new Bundle(); + replyData.putString("data", jsonData); + createAndSendReply(message, GethMessages.MSG_ACCOUNT_RECOVERED, replyData); + } + private void login(Message message) { Bundle data = message.getData(); String address = data.getString("address"); String password = data.getString("password"); - // TODO: remove third argument - String result = Statusgo.UnlockAccount(address, password, 0); - Log.d(TAG, "Unlocked account: " + result); + String result = Statusgo.Login(address, password); + Log.d(TAG, "Loggedin account: " + result); Bundle replyData = new Bundle(); replyData.putString("result", result); @@ -220,9 +235,10 @@ public class GethService extends Service { private void completeTransaction(Message message){ Bundle data = message.getData(); String hash = data.getString("hash"); + String password = data.getString("password"); Log.d(TAG, "Before CompleteTransaction: " + hash); - String result = Statusgo.CompleteTransaction(hash); + String result = Statusgo.CompleteTransaction(hash, password); Log.d(TAG, "After CompleteTransaction: " + result); Bundle replyData = new Bundle(); diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs index edf7a7e8a8..900c494954 100644 --- a/src/status_im/accounts/handlers.cljs +++ b/src/status_im/accounts/handlers.cljs @@ -1,5 +1,5 @@ (ns status-im.accounts.handlers - (:require [status-im.models.accounts :as accounts] + (:require [status-im.models.accounts :as accounts-model] [re-frame.core :refer [register-handler after dispatch dispatch-sync debug]] [status-im.utils.logging :as log] [status-im.protocol.api :as api] @@ -14,13 +14,14 @@ [status-im.i18n :refer [label]] [status-im.constants :refer [content-type-command-request]] status-im.accounts.login.handlers + status-im.accounts.recover.handlers [clojure.string :as str] [status-im.utils.datetime :as time] [status-im.utils.handlers :as u])) (defn save-account [_ [_ account]] - (accounts/save-accounts [account] true)) + (accounts-model/save-accounts [account] true)) (register-handler :add-account @@ -55,7 +56,7 @@ (defn save-account-to-realm! [{:keys [current-account-id accounts]} _] - (accounts/save-accounts [(get accounts current-account-id)] true)) + (accounts-model/save-accounts [(get accounts current-account-id)] true)) (defn send-account-update [{:keys [current-account-id accounts]} _] @@ -82,40 +83,17 @@ (when needs-update? (dispatch [:account-update])))))) -(defn initialize-account [{:keys [accounts] :as db} address] - (let [is-login-screen? (= (:view-id db) :login)] - (dispatch [:set :login {}]) - (dispatch [:set :current-account-id address]) - (let [key (:public-key (accounts address))] - (dispatch [:set :current-public-key key])) - (dispatch [:initialize-account address]) - (when is-login-screen? (dispatch [:navigate-to-clean default-view])))) +(defn set-current-account + [{:keys [accounts] :as db} [_ address]] + (let [key (:public-key (accounts address))] + (-> db + (assoc :current-account-id address) + (assoc :current-public-key key)))) -(defn logged-in [db address] - (let [is-login-screen? (= (:view-id db) :login) - new-account? (not is-login-screen?)] - (log/debug "Logged in: ") - (realm/change-account-realm address new-account? - #(if (nil? %) - (initialize-account db address) - (log/debug "Error changing acount realm: " %))))) - -(register-handler - :login-account - (u/side-effect! - (fn [db [_ address password]] - (geth/login address password - (fn [result] - (let [data (json->clj result) - error (:error data) - success (zero? (count error))] - (log/debug "Logged in account: ") - (if success - (logged-in db address) - (dispatch [:set-in [:login :error] error])))))))) +(register-handler :set-current-account set-current-account) (defn load-accounts! [db _] - (let [accounts (->> (accounts/get-accounts) + (let [accounts (->> (accounts-model/get-accounts) (map (fn [{:keys [address] :as account}] [address account])) (into {}))] diff --git a/src/status_im/accounts/login/handlers.cljs b/src/status_im/accounts/login/handlers.cljs index 5a00d18935..df790b19b7 100644 --- a/src/status_im/accounts/login/handlers.cljs +++ b/src/status_im/accounts/login/handlers.cljs @@ -1,10 +1,59 @@ (ns status-im.accounts.login.handlers (:require [re-frame.core :refer [register-handler after dispatch]] - [status-im.utils.handlers :as u])) + [status-im.utils.handlers :as u] + [status-im.utils.logging :as log] + [status-im.utils.types :refer [json->clj]] + [status-im.db :refer [default-view]] + [status-im.persistence.realm.core :as realm] + [status-im.components.geth :as geth])) (defn set-login-from-qr [{:keys [login] :as db} [_ _ login-info]] (assoc db :login (merge login login-info))) -(register-handler :set-login-from-qr set-login-from-qr) \ No newline at end of file +(register-handler :set-login-from-qr set-login-from-qr) + +(defn initialize-account + [address new-account?] + (dispatch [:set :login {}]) + (dispatch [:set-current-account address]) + (dispatch [:initialize-account address]) + (when new-account? + (do + (dispatch [:navigate-to-clean :accounts]) + (dispatch [:navigate-to default-view])))) + +(register-handler + :change-realm-account + (u/side-effect! + (fn [db [_ address new-account? callback]] + (realm/change-account-realm address new-account? + #(callback % address new-account?))))) + +(defn on-account-changed + [error address new-account?] + (if (nil? error) + (initialize-account address true) + (log/debug "Error changing acount realm: " error))) + +(defn logged-in + [db address] + (let [is-login-screen? (= (:view-id db) :login) + new-account? (not is-login-screen?)] + (log/debug "Logged in: ") + (dispatch [:change-realm-account address new-account? on-account-changed]))) + +(register-handler + :login-account + (u/side-effect! + (fn [db [_ address password]] + (geth/login address password + (fn [result] + (let [data (json->clj result) + error (:error data) + success (zero? (count error))] + (log/debug "Logged in account: ") + (if success + (logged-in db address) + (dispatch [:set-in [:login :error] error])))))))) \ No newline at end of file diff --git a/src/status_im/accounts/login/screen.cljs b/src/status_im/accounts/login/screen.cljs index 7ff96acf30..0a9ddb2485 100644 --- a/src/status_im/accounts/login/screen.cljs +++ b/src/status_im/accounts/login/screen.cljs @@ -81,14 +81,6 @@ [address-input (or address "")] [password-input error]]] [view st/bottom-actions-container - (when (= keyboard-height 0) - [view st/recover-button-container - [touchable-highlight - {:on-press #()} - [view st/recover-button - [text {:style st/recover-button-text - :platform-specific platform-specific} - (label :t/recover-access)]]]]) [view st/connect-button-container [touchable-highlight {:on-press #(dispatch [:login-account address password])} diff --git a/src/status_im/accounts/login/styles.cljs b/src/status_im/accounts/login/styles.cljs index deeff1033a..daf7f2bb27 100644 --- a/src/status_im/accounts/login/styles.cljs +++ b/src/status_im/accounts/login/styles.cljs @@ -34,20 +34,6 @@ :right 0 :bottom 0}) -(def recover-button-container - {:flex 1}) - -(def recover-button - {:flex 1 - :alignItems :center - :paddingVertical 16 - :paddingHorizontal 28}) - -(def recover-button-text - {:flex 1 - :color color-white - :fontSize 16}) - (def connect-button-container {:flex 1}) diff --git a/src/status_im/accounts/recover/handlers.cljs b/src/status_im/accounts/recover/handlers.cljs new file mode 100644 index 0000000000..81cb14a734 --- /dev/null +++ b/src/status_im/accounts/recover/handlers.cljs @@ -0,0 +1,37 @@ +(ns status-im.accounts.recover.handlers + (:require [re-frame.core :refer [register-handler after dispatch dispatch-sync]] + [status-im.components.geth :as geth] + [status-im.utils.handlers :as u] + [status-im.utils.types :refer [json->clj]] + [status-im.utils.identicon :refer [identicon]] + [status-im.chat.sign-up :as sign-up-service] + [status-im.utils.logging :as log] + [clojure.string :as str])) + +(defn on-account-changed + [error address new-account?] + (dispatch [:navigate-to-clean :accounts])) + +(defn account-recovered [result password] + (let [_ (log/debug result) + data (json->clj result) + public-key (:pubkey data) + address (:address data) + account {:public-key public-key + :address address + :name address + :photo-path (identicon public-key)}] + (log/debug "account-recovered") + (when (not (str/blank? public-key)) + (do + (dispatch [:set-in [:recover :passphrase] ""]) + (dispatch [:set-in [:recover :password] ""]) + (dispatch [:add-account account]) + (dispatch [:navigate-back]))))) + +(defn recover-account + [{:keys [recover] :as db} [_ passphrase password]] + (geth/recover-account passphrase password (fn [result] (account-recovered result password))) + db) + +(register-handler :recover-account recover-account) \ No newline at end of file diff --git a/src/status_im/accounts/recover/screen.cljs b/src/status_im/accounts/recover/screen.cljs new file mode 100644 index 0000000000..5ce0bbf048 --- /dev/null +++ b/src/status_im/accounts/recover/screen.cljs @@ -0,0 +1,111 @@ +(ns status-im.accounts.recover.screen + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [status-im.components.react :refer [view + text + text-input + image + linear-gradient + touchable-highlight]] + [status-im.components.status-bar :refer [status-bar]] + [status-im.components.toolbar :refer [toolbar]] + [status-im.components.text-field.view :refer [text-field]] + [status-im.components.styles :refer [color-purple + color-white + icon-back + icon-search + toolbar-title-container + toolbar-title-text + toolbar-gradient + button-input]] + [status-im.components.react :refer [linear-gradient]] + [status-im.i18n :refer [label]] + [status-im.accounts.recover.styles :as st] + [status-im.accounts.recover.validations :as v] + [cljs.spec :as s] + [clojure.string :as str] + [status-im.utils.logging :as log])) + +(defn toolbar-title + [platform-specific] + [view toolbar-title-container + [text {:style toolbar-title-text + :platform-specific platform-specific + :font :medium} + (label :t/recover-from-passphrase)]]) + +(defview passphrase-input [passphrase] + [error [:get-in [:recover :passphrase-error]]] + (let [error (if (str/blank? passphrase) "" error) + error (if (s/valid? ::v/passphrase passphrase) + error + (label :t/enter-valid-passphrase))] + [view + [text-field + {:value passphrase + :error error + :errorColor "#7099e6" + :label (label :t/passphrase) + :labelColor "#838c93de" + :lineColor "#0000001f" + :inputStyle st/input-style + :wrapperStyle (merge button-input st/address-input-wrapper) + :onChangeText #(dispatch [:set-in [:recover :passphrase] %])}]])) + +(defview password-input [password] + [error [:get-in [:recover :password-error]]] + (let [error (if (str/blank? password) "" error) + error (if (s/valid? ::v/password password) + error + (label :t/enter-valid-password))] + [view + [text-field + {:value password + :error error + :errorColor "#7099e6" + :label (label :t/password) + :labelColor "#838c93de" + :lineColor "#0000001f" + :inputStyle st/input-style + :onChangeText #(dispatch [:set-in [:recover :password] %])}]])) + +(defview recover [{platform-specific :platform-specific}] + [{:keys [passphrase password passphrase-error password-error]} [:get :recover]] + (let [valid-form? (and + (s/valid? ::v/passphrase passphrase) + (s/valid? ::v/password password)) + gradient-colors ["rgba(24, 52, 76, 0.165)" + "rgba(24, 52, 76, 0.085)" + "rgba(24, 52, 76, 0)"] + _ (log/debug passphrase " - " password)] + [view st/screen-container + [status-bar {:platform-specific platform-specific + :type :transparent}] + [toolbar {:background-color :transparent + :nav-action {:image {:source {:uri :icon_back} + :style icon-back} + :handler #(dispatch [:navigate-back])} + :custom-content [toolbar-title platform-specific] + :action {:image {:style icon-search} + :handler #()}}] + [linear-gradient {:locations [0 0.6 1] + :colors gradient-colors + :style toolbar-gradient}] + [view st/recover-explain-container + [text {:style st/recover-explain-text + :platform-specific platform-specific + :font :medium} + (label :t/recover-explain)]] + [view st/form-container + [view st/form-container-inner + [passphrase-input (or passphrase "")] + [password-input (or password "")]]] + [view st/bottom-actions-container + [view st/recover-button-container + [touchable-highlight + {:on-press #(when valid-form? + (dispatch [:recover-account passphrase password]))} + [view (st/recover-button valid-form?) + [text {:style st/recover-button-text + :platform-specific platform-specific} + (label :t/recover)]]]]]])) diff --git a/src/status_im/accounts/recover/styles.cljs b/src/status_im/accounts/recover/styles.cljs new file mode 100644 index 0000000000..156c63fa12 --- /dev/null +++ b/src/status_im/accounts/recover/styles.cljs @@ -0,0 +1,71 @@ +(ns status-im.accounts.recover.styles + (:require [status-im.components.styles :refer [title-font + text1-color + color-white + toolbar-background2 + online-color]])) + + +(def screen-container + {:flex 1 + :color :white + :background-color color-white}) + +(def gradient-background + {:position :absolute + :top 0 + :right 0 + :bottom 0 + :left 0}) + +(def recover-explain-container + {:padding-horizontal 35 + :padding-top 20 + :justify-content :center}) + +(def recover-explain-text + {:color "#838c93de" + :font-size 16 + :line-height 20 + :text-align :center}) + +(def form-container + {:flex 1 + :flex-direction "row" + :justifyContent "center"}) + +(def form-container-inner + {:flex 1 + :padding-bottom 100 + :margin-left 16}) + +(def bottom-actions-container + {:position :absolute + :left 0 + :right 0 + :bottom 0}) + +(def recover-button-container + {:flex 1}) + +(defn recover-button [valid-form?] + {:backgroundColor (if valid-form? "#7099e6" :gray) + :color :white + :flex 1 + :alignItems :center + :paddingVertical 16 + :paddingHorizontal 28}) + +(def recover-button-text + {:color color-white + :fontSize 16}) + +(def input-style + {:color "#323232" + :font-size 12}) + +(def scan-label + {:color :white}) + +(def address-input-wrapper + {}) \ No newline at end of file diff --git a/src/status_im/accounts/recover/validations.cljs b/src/status_im/accounts/recover/validations.cljs new file mode 100644 index 0000000000..e6fdc7ca90 --- /dev/null +++ b/src/status_im/accounts/recover/validations.cljs @@ -0,0 +1,8 @@ +(ns status-im.accounts.recover.validations + (:require [cljs.spec :as s] + [cljsjs.web3] + [status-im.persistence.realm.core :as realm])) + +(s/def ::not-empty-string (s/and string? not-empty)) +(s/def ::passphrase ::not-empty-string) +(s/def ::password ::not-empty-string) diff --git a/src/status_im/accounts/screen.cljs b/src/status_im/accounts/screen.cljs index ca5a64ebfc..25695f04f8 100644 --- a/src/status_im/accounts/screen.cljs +++ b/src/status_im/accounts/screen.cljs @@ -25,6 +25,7 @@ white-form-text-input]] [status-im.utils.listview :as lw] [status-im.accounts.views.account :refer [account-view]] + [status-im.chat.sign-up :as sign-up-service] [status-im.i18n :refer [label]] [status-im.accounts.styles :as st] [status-im.utils.logging :as log])) @@ -78,13 +79,22 @@ :renderRow render-row :style st/account-list :contentContainerStyle (st/account-list-content (count accounts))}] - [view st/add-account-button-container - [touchable-highlight {:on-press create-account - :accessibility-label :create-account} - [view st/add-account-button - [image {:source {:uri :icon_add} - :style st/icon-plus}] - [text {:style st/add-account-text - :platform-specific platform-specific - :font :default} - (label :t/add-account)]]]]]])) + [view st/bottom-actions-container + [view st/recover-button-container + [touchable-highlight + {:on-press #(dispatch [:navigate-to :recover])} + [view st/recover-button + [text {:style st/recover-button-text + :platform-specific platform-specific} + (label :t/recover-access)]]]] + [view st/add-account-button-container + [touchable-highlight {:on-press create-account + :accessibility-label :create-account} + [view st/add-account-button + [image {:source {:uri :icon_add} + :style st/icon-plus}] + [text {:style st/add-account-text + :platform-specific platform-specific + :font :default} + (label :t/add-account)]]]] + ]]])) diff --git a/src/status_im/accounts/styles.cljs b/src/status_im/accounts/styles.cljs index 56fe161755..804ebb82fe 100644 --- a/src/status_im/accounts/styles.cljs +++ b/src/status_im/accounts/styles.cljs @@ -76,12 +76,16 @@ :alignItems :center :justifyContent :center}) +(def bottom-actions-container + {:position :absolute + :left 0 + :right 0 + :bottom 0}) + (def add-account-button-container - {:position :absolute - :bottom 16 - :height 50 - :left 100 - :right 100 + {:flex 1 + :paddingVertical 16 + :paddingHorizontal 28 :justifyContent :center :alignItems :center}) @@ -99,3 +103,17 @@ :color :white :fontSize 16 :marginLeft 8}) + +(def recover-button-container + {:flex 1}) + +(def recover-button + {:flex 1 + :alignItems :center + :paddingVertical 16 + :paddingHorizontal 28}) + +(def recover-button-text + {:flex 1 + :color color-white + :fontSize 16}) diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index a9084f4c47..7681e112e4 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -18,6 +18,7 @@ [status-im.discovery.search-results :refer [discovery-search-results]] [status-im.chat.screen :refer [chat]] [status-im.accounts.login.screen :refer [login]] + [status-im.accounts.recover.screen :refer [recover]] [status-im.accounts.screen :refer [accounts]] [status-im.transactions.screen :refer [confirm]] [status-im.chats-list.screen :refer [chats-list]] @@ -49,7 +50,6 @@ (defn app-root [] (let [signed-up (subscribe [:get :signed-up]) - _ (log/debug "signed up: " @signed-up) view-id (subscribe [:get :view-id]) account-id (subscribe [:get :current-account-id]) keyboard-height (subscribe [:get :keyboard-height])] @@ -78,8 +78,10 @@ (let [startup-view (if @account-id (if @signed-up @view-id - :chat) - (if (contains? #{:login :chat} @view-id) + (if (= @view-id :accounts) + :accounts + :chat)) + (if (contains? #{:login :chat :recover} @view-id) @view-id :accounts))] (log/debug startup-view) @@ -101,6 +103,7 @@ :profile-photo-capture profile-photo-capture :accounts accounts :login login + :recover recover :confirm confirm :my-profile my-profile)] [component {:platform-specific {:styles styles diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 840eec291f..9faa0ec5f5 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -161,9 +161,26 @@ (fn [db [_ {:keys [chat-id msg-id]}]] (set-message-shown db chat-id msg-id))) +(defn init-console-chat + [{:keys [chats] :as db} existing-account?] + (let [chat-id "console" + new-chat sign-up-service/console-chat] + (if (chats chat-id) + db + (do + (chats/create-chat new-chat) + (sign-up-service/intro existing-account?) + (when existing-account? + (sign-up-service/start-signup)) + (-> db + (assoc :new-chat new-chat) + (update :chats assoc chat-id new-chat) + (update :chats-ids conj chat-id) + (assoc :current-chat-id "console")))))) + (register-handler :init-console-chat - (fn [db [_]] - (sign-up-service/init db))) + (fn [db _] + (init-console-chat db false))) (register-handler :save-password (fn [db [_ password]] @@ -221,15 +238,18 @@ [chat-id chat])) (into {})) ids (set (keys chats))] + (-> db (assoc :chats chats) (assoc :chats-ids ids) - (dissoc :loaded-chats)))) + (dissoc :loaded-chats) + (init-console-chat true)))) (defn load-chats! [db _] (assoc db :loaded-chats (chats/chats-list))) +;TODO: check if its new account / signup status / create console chat (register-handler :initialize-chats (after #(dispatch [:load-unviewed-messages!])) ((enrich initialize-chats) load-chats!)) diff --git a/src/status_im/chat/sign_up.cljs b/src/status_im/chat/sign_up.cljs index 9d0ef738c3..65afe63c91 100644 --- a/src/status_im/chat/sign_up.cljs +++ b/src/status_im/chat/sign_up.cljs @@ -24,7 +24,7 @@ :content-type text-content-type :outgoing true}) -(defn- set-signed-up [db signed-up] +(defn set-signed-up [db signed-up] (s/put kv/kv-store :signed-up signed-up) (assoc db :signed-up signed-up)) @@ -94,6 +94,18 @@ (when (= :failed status) (on-sign-up-response (label :t/incorrect-code))))) +(defn start-signup [] + (let [msg-id (random/id)] + (dispatch [:received-message + {:msg-id msg-id + :content (command-content + :phone + (label :t/phone-number-required)) + :content-type content-type-command-request + :outgoing false + :from "console" + :to "me"}]))) + ;; -- Saving password ---------------------------------------- (defn save-password [password] ;; TODO validate and save password @@ -115,7 +127,7 @@ :new? false}]) (dispatch [:received-message {:msg-id (random/id) - :content (label :t/passphrase) + :content (label :t/here-is-your-passphrase) :content-type text-content-type :outgoing false :from "console" @@ -141,16 +153,9 @@ :to "me" :new? false}]) ;; TODO highlight '!phone' - (let [msg-id (random/id)] - (dispatch [:received-message - {:msg-id msg-id - :content (command-content - :phone - (label :t/phone-number-required)) - :content-type content-type-command-request - :outgoing false - :from "console" - :to "me"}]))) + (start-signup)) + + (def intro-status {:msg-id "intro-status" @@ -162,7 +167,7 @@ :outgoing false :to "me"}) -(defn intro [db] +(defn intro [logged-in?] (dispatch [:received-message intro-status]) (dispatch [:received-message {:msg-id "intro-message1" @@ -171,24 +176,24 @@ :outgoing false :from "console" :to "me"}]) - (dispatch [:received-message - {:msg-id "intro-message2" - :content (label :t/intro-message2) - :content-type text-content-type - :outgoing false - :from "console" - :to "me"}]) - (let [msg-id "into-message3"] + (when-not logged-in? (dispatch [:received-message - {:msg-id msg-id + {:msg-id "intro-message2" + :content (label :t/intro-message2) + :content-type text-content-type + :outgoing false + :from "console" + :to "me"}]) + + (dispatch [:received-message + {:msg-id "intro-message3" :content (command-content :keypair (label :t/keypair-generated)) :content-type content-type-command-request :outgoing false :from "console" - :to "me"}])) - db) + :to "me"}]))) (def console-chat {:chat-id "console" @@ -203,21 +208,3 @@ :contacts [{:identity "console" :text-color "#FFFFFF" :background-color "#AB7967"}]}) - -(defn create-chat [handler] - (fn [db] - (let [{:keys [new-chat] :as db'} (handler db)] - (when new-chat - (c/create-chat new-chat)) - (dissoc db' :new-chat)))) - -(def init - (create-chat - (fn [{:keys [chats] :as db}] - (if (chats "console") - db - (-> db - (assoc-in [:chats "console"] console-chat) - (assoc :new-chat console-chat) - (assoc :current-chat-id "console") - (intro)))))) diff --git a/src/status_im/components/geth.cljs b/src/status_im/components/geth.cljs index 6d7ca4acaa..c2632dc1a8 100644 --- a/src/status_im/components/geth.cljs +++ b/src/status_im/components/geth.cljs @@ -23,11 +23,15 @@ (when geth (.createAccount geth password on-result))) +(defn recover-account [passphrase password on-result] + (when geth + (.recoverAccount geth passphrase password on-result))) + (defn login [address password on-result] (when geth (.login geth address password on-result))) (defn complete-transaction - [hash callback] + [hash password callback] (when geth - (.completeTransaction geth hash callback))) + (.completeTransaction geth hash password callback))) diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs index dfb7417092..d48bbf1824 100644 --- a/src/status_im/components/styles.cljs +++ b/src/status_im/components/styles.cljs @@ -112,3 +112,6 @@ (def button-input {:flex 1 :flexDirection :column}) + +(def toolbar-gradient + {:height 4}) \ No newline at end of file diff --git a/src/status_im/transactions/handlers.cljs b/src/status_im/transactions/handlers.cljs index ed686683cc..e2c47498f7 100644 --- a/src/status_im/transactions/handlers.cljs +++ b/src/status_im/transactions/handlers.cljs @@ -12,25 +12,25 @@ [{:keys [transactions-queue] :as db} _] (assoc db :transactions transactions-queue)) -(defn on-unlock [hashes] - (fn [result-str] - (let [{:keys [error]} (t/json->clj result-str)] - ;; todo: add message about wrong password - (if (s/blank? error) - (do - (dispatch [:set :wrong-password? false]) - (doseq [hash hashes] - (g/complete-transaction - hash - #(dispatch [:transaction-completed hash %]))) - (dispatch [:navigate-back])) - (dispatch [:set :wrong-password? true]))))) +(defn on-unlock + [hashes password] + ;; todo: add message about wrong password + (do + ;(dispatch [:set :wrong-password? false]) + (doseq [hash hashes] + (g/complete-transaction + hash + password + #(dispatch [:transaction-completed hash %]))) + (dispatch [:navigate-back]))) + ;(dispatch [:set :wrong-password? true]) + (register-handler :accept-transactions (u/side-effect! (fn [{:keys [transactions current-account-id]} [_ password]] (let [hashes (keys transactions)] - (g/login current-account-id password (on-unlock hashes)))))) + (on-unlock hashes password))))) (register-handler :deny-transactions (u/side-effect! diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 07187c9ce6..a70bee6086 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -63,7 +63,7 @@ "it's me the Console nice to meet you!") :generate-passphrase (str "I'll generate a passphrase for you so you can restore your " "access or log in from another device") - :passphrase "Here's your passphrase:" + :here-is-your-passphrase "Here's your passphrase:" :written-down "Make sure you had securely written it down" :phone-number-required (str "Your phone number is also required to use the app. Type the " "exclamation mark or hit the icon to open the command list " @@ -72,7 +72,7 @@ "and public exchange with candidates " "in the US presidential election") :intro-message1 "Hello there! It's Status a Dapp browser in your phone." - :intro-message2 (str "Status1 uses a highly secure key-pair authentication type " + :intro-message2 (str "Status uses a highly secure key-pair authentication type " "to provide you a reliable way to access your account") :keypair-generated (str "A key pair has been generated and saved to your device. " "Create a password to secure your key") @@ -153,14 +153,22 @@ ;login - :recover-access "Recover access" :connect "Connect" :address "Address" :password "Password" :login "Login" :wrong-password "Wrong password" + ;recover + :recover-from-passphrase "Recover from passphrase" + :recover-explain "Please enter the passphrase for your password to recover access" + :passphrase "Passphrase" + :recover "Recover" + :enter-valid-passphrase "Please enter a passphrase" + :enter-valid-password "Please enter a password" + ;accounts + :recover-access "Recover access" :add-account "Add account" ;validation @@ -178,4 +186,5 @@ :one-more-item "One more item" :fee "Fee" :value "Value" + })