Onboarding sign-in
Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
This commit is contained in:
parent
b78bb456a4
commit
433f840f76
|
@ -3,4 +3,4 @@
|
||||||
(def figwheel-urls {:android "ws://localhost:3449/figwheel-ws",
|
(def figwheel-urls {:android "ws://localhost:3449/figwheel-ws",
|
||||||
:ios "ws://192.168.0.9:3449/figwheel-ws",
|
:ios "ws://192.168.0.9:3449/figwheel-ws",
|
||||||
:desktop "ws://localhost:3449/figwheel-ws"}
|
:desktop "ws://localhost:3449/figwheel-ws"}
|
||||||
)
|
)
|
||||||
|
|
|
@ -141,17 +141,19 @@
|
||||||
|
|
||||||
(fx/defn intro-wizard
|
(fx/defn intro-wizard
|
||||||
{:events [:accounts.create.ui/intro-wizard]}
|
{:events [:accounts.create.ui/intro-wizard]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx} first-time-setup?]
|
||||||
(fx/merge {:db (assoc db :intro-wizard {:step :generate-key
|
(fx/merge {:db (assoc db :intro-wizard {:step :generate-key
|
||||||
:weak-password? true
|
:weak-password? true
|
||||||
:encrypt-with-password? true}
|
:encrypt-with-password? true
|
||||||
|
:first-time-setup? first-time-setup?}
|
||||||
:accounts/new-installation-id (random/guid))}
|
:accounts/new-installation-id (random/guid))}
|
||||||
(navigation/navigate-to-cofx :intro-wizard nil)))
|
(navigation/navigate-to-cofx :intro-wizard nil)))
|
||||||
|
|
||||||
(fx/defn intro-step-back
|
(fx/defn intro-step-back
|
||||||
{:events [:intro-wizard/step-back-pressed]}
|
{:events [:intro-wizard/step-back-pressed]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
(let [step (get-in db [:intro-wizard :step])]
|
(let [step (get-in db [:intro-wizard :step])
|
||||||
|
first-time-setup? (get-in db [:intro-wizard :first-time-setup?])]
|
||||||
(if (not= :generate-key step)
|
(if (not= :generate-key step)
|
||||||
(fx/merge {:db (cond-> (assoc-in db [:intro-wizard :step] (dec-step step))
|
(fx/merge {:db (cond-> (assoc-in db [:intro-wizard :step] (dec-step step))
|
||||||
(#{:create-code :confirm-code} step)
|
(#{:create-code :confirm-code} step)
|
||||||
|
@ -161,7 +163,7 @@
|
||||||
(navigation/navigate-to-cofx :intro-wizard nil))
|
(navigation/navigate-to-cofx :intro-wizard nil))
|
||||||
|
|
||||||
(fx/merge {:db (dissoc db :intro-wizard)}
|
(fx/merge {:db (dissoc db :intro-wizard)}
|
||||||
(navigation/navigate-to-clean :intro nil)))))
|
(navigation/navigate-to-clean (if first-time-setup? :intro :accounts) nil)))))
|
||||||
|
|
||||||
(fx/defn exit-wizard [{:keys [db] :as cofx}]
|
(fx/defn exit-wizard [{:keys [db] :as cofx}]
|
||||||
(fx/merge {:db (dissoc db :intro-wizard)}
|
(fx/merge {:db (dissoc db :intro-wizard)}
|
||||||
|
@ -196,26 +198,31 @@
|
||||||
(fx/defn intro-step-forward
|
(fx/defn intro-step-forward
|
||||||
{:events [:intro-wizard/step-forward-pressed]}
|
{:events [:intro-wizard/step-forward-pressed]}
|
||||||
[{:keys [db] :as cofx} {:keys [skip?] :as opts}]
|
[{:keys [db] :as cofx} {:keys [skip?] :as opts}]
|
||||||
(let [step (get-in db [:intro-wizard :step])]
|
(let [step (get-in db [:intro-wizard :step])
|
||||||
(cond (= step :enable-notifications)
|
first-time-setup? (get-in db [:intro-wizard :first-time-setup?])]
|
||||||
|
(cond (confirm-failure? db)
|
||||||
|
(on-confirm-failure cofx)
|
||||||
|
|
||||||
|
(or (= step :enable-notifications)
|
||||||
|
(and (not first-time-setup?) (= step :confirm-code)
|
||||||
|
(:accounts/login db)))
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
(when-not skip? {:notifications/request-notifications-permissions nil})
|
(when (and (= step :enable-notifications) (not skip?))
|
||||||
|
{:notifications/request-notifications-permissions nil})
|
||||||
exit-wizard)
|
exit-wizard)
|
||||||
|
|
||||||
(= step :generate-key)
|
(= step :generate-key)
|
||||||
(init-key-generation cofx)
|
(init-key-generation cofx)
|
||||||
|
|
||||||
(confirm-failure? db)
|
|
||||||
(on-confirm-failure cofx)
|
|
||||||
|
|
||||||
(= step :create-code)
|
(= step :create-code)
|
||||||
(store-key-code cofx)
|
(store-key-code cofx)
|
||||||
|
|
||||||
:else (fx/merge {:db (assoc-in db [:intro-wizard :step]
|
(and (= step :confirm-code)
|
||||||
(inc-step step))}
|
(not (:accounts/login db)))
|
||||||
(when (and (= step :confirm-code)
|
(create-account cofx)
|
||||||
(not (:accounts/login db)))
|
|
||||||
(create-account cofx))))))
|
:else {:db (assoc-in db [:intro-wizard :step]
|
||||||
|
(inc-step step))})))
|
||||||
|
|
||||||
(fx/defn on-account-created
|
(fx/defn on-account-created
|
||||||
[{:keys [signing-phrase
|
[{:keys [signing-phrase
|
||||||
|
|
|
@ -301,11 +301,12 @@
|
||||||
:keychain/get-user-password [address
|
:keychain/get-user-password [address
|
||||||
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success % address])]})
|
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success % address])]})
|
||||||
|
|
||||||
(fx/defn open-login [{:keys [db] :as cofx} address photo-path name]
|
(fx/defn open-login [{:keys [db] :as cofx} address photo-path name public-key]
|
||||||
(let [keycard-account? (get-in db [:accounts/accounts address :keycard-instance-uid])]
|
(let [keycard-account? (get-in db [:accounts/accounts address :keycard-instance-uid])]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(update :accounts/login assoc
|
(update :accounts/login assoc
|
||||||
|
:public-key public-key
|
||||||
:address address
|
:address address
|
||||||
:photo-path photo-path
|
:photo-path photo-path
|
||||||
:name name)
|
:name name)
|
||||||
|
|
|
@ -341,8 +341,8 @@
|
||||||
|
|
||||||
(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 public-key]]
|
||||||
(accounts.login/open-login cofx address photo-path name)))
|
(accounts.login/open-login cofx address photo-path name public-key)))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:accounts.login.callback/get-user-password-success
|
:accounts.login.callback/get-user-password-success
|
||||||
|
|
|
@ -388,7 +388,7 @@
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (assoc-in db [:hardwallet :flow] :create)}
|
{:db (assoc-in db [:hardwallet :flow] :create)}
|
||||||
(navigation/navigate-to-cofx :hardwallet-authentication-method nil))
|
(navigation/navigate-to-cofx :hardwallet-authentication-method nil))
|
||||||
(accounts.create/navigate-to-create-account-screen cofx)))
|
(accounts.create/intro-wizard cofx false)))
|
||||||
|
|
||||||
(fx/defn navigate-to-recover-method
|
(fx/defn navigate-to-recover-method
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
|
|
|
@ -151,8 +151,8 @@
|
||||||
(:public-key account)))
|
(:public-key account)))
|
||||||
%)
|
%)
|
||||||
#(sort-by :last-sign-in > %))
|
#(sort-by :last-sign-in > %))
|
||||||
{:keys [address photo-path name]} (first (selection-fn (vals accounts)))]
|
{:keys [address public-key photo-path name]} (first (selection-fn (vals accounts)))]
|
||||||
(accounts.login/open-login cofx address photo-path name)))))
|
(accounts.login/open-login cofx address photo-path name public-key)))))
|
||||||
|
|
||||||
(fx/defn load-accounts-and-initialize-views
|
(fx/defn load-accounts-and-initialize-views
|
||||||
"DB has been decrypted, load accounts and initialize-view"
|
"DB has been decrypted, load accounts and initialize-view"
|
||||||
|
|
|
@ -26,5 +26,9 @@
|
||||||
|
|
||||||
(defn error [label?]
|
(defn error [label?]
|
||||||
{:bottom-value (if label? 20 0)
|
{:bottom-value (if label? 20 0)
|
||||||
:color colors/red-light
|
:container-style {:shadow-offset {:width 0 :height 1}
|
||||||
|
:shadow-radius 6
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-color colors/gray
|
||||||
|
:elevation 2}
|
||||||
:font-size 12})
|
:font-size 12})
|
||||||
|
|
|
@ -15,15 +15,25 @@
|
||||||
:align-items :center
|
:align-items :center
|
||||||
:justify-content :center})
|
:justify-content :center})
|
||||||
|
|
||||||
(def sign-you-in
|
(def processing
|
||||||
{:margin-top 16
|
{:margin-top 16
|
||||||
:font-size 13})
|
:color colors/gray})
|
||||||
|
|
||||||
|
(def bottom-button
|
||||||
|
{:padding-horizontal 24
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
(def bottom-button-container
|
(def bottom-button-container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:margin-horizontal 12
|
:padding-horizontal 12
|
||||||
:margin-vertical 15
|
:padding-vertical 8
|
||||||
:align-items :center})
|
:border-top-width 1
|
||||||
|
:border-top-color colors/gray-lighter
|
||||||
|
:justify-content :space-between
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
(def login-badge
|
(def login-badge
|
||||||
{:align-items :center})
|
{:align-items :center})
|
||||||
|
@ -31,18 +41,21 @@
|
||||||
(def login-badge-image-size 56)
|
(def login-badge-image-size 56)
|
||||||
|
|
||||||
(def login-badge-name
|
(def login-badge-name
|
||||||
{:margin-top 8})
|
{:margin-top 10
|
||||||
|
:text-align :center
|
||||||
|
:font-weight "500"})
|
||||||
|
|
||||||
|
(def login-badge-pubkey
|
||||||
|
{:margin-top 4
|
||||||
|
:text-align :center
|
||||||
|
:color colors/gray
|
||||||
|
:font-family "monospace"})
|
||||||
|
|
||||||
(def password-container
|
(def password-container
|
||||||
{:margin-top 24
|
{:margin-top 24
|
||||||
:android {:margin-top 11
|
:android {:margin-top 11
|
||||||
:padding-top 13}})
|
:padding-top 13}})
|
||||||
|
|
||||||
(def save-password-checkbox-container
|
|
||||||
{:margin-top 0
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center})
|
|
||||||
|
|
||||||
(def save-password-unavailable
|
(def save-password-unavailable
|
||||||
{:margin-top 8
|
{:margin-top 8
|
||||||
:width "100%"
|
:width "100%"
|
||||||
|
|
|
@ -2,14 +2,16 @@
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[status-im.ui.screens.accounts.styles :as ast]
|
[status-im.ui.screens.accounts.styles :as ast]
|
||||||
[status-im.ui.screens.profile.components.views :as profile.components]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.text-input.view :as text-input]
|
[status-im.ui.components.text-input.view :as text-input]
|
||||||
[status-im.ui.components.status-bar.view :as status-bar]
|
[status-im.ui.components.status-bar.view :as status-bar]
|
||||||
[status-im.ui.components.toolbar.view :as toolbar]
|
[status-im.ui.components.toolbar.view :as toolbar]
|
||||||
|
[status-im.ui.components.checkbox.view :as checkbox]
|
||||||
[status-im.ui.components.toolbar.actions :as act]
|
[status-im.ui.components.toolbar.actions :as act]
|
||||||
[status-im.ui.screens.accounts.login.styles :as styles]
|
[status-im.ui.screens.accounts.login.styles :as styles]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.ui.components.react :as components]
|
[status-im.ui.components.react :as components]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
|
@ -19,10 +21,11 @@
|
||||||
|
|
||||||
(defn login-toolbar [can-navigate-back?]
|
(defn login-toolbar [can-navigate-back?]
|
||||||
[toolbar/toolbar
|
[toolbar/toolbar
|
||||||
nil
|
{:style {:border-bottom-width 0
|
||||||
|
:margin-top 0}}
|
||||||
(when can-navigate-back?
|
(when can-navigate-back?
|
||||||
[toolbar/nav-button act/default-back])
|
[toolbar/nav-button (act/back #(re-frame/dispatch [:navigate-to-clean :accounts]))])
|
||||||
[toolbar/content-title (i18n/label :t/sign-in-to-status)]])
|
nil])
|
||||||
|
|
||||||
(defn login-account [password-text-input]
|
(defn login-account [password-text-input]
|
||||||
(.blur password-text-input)
|
(.blur password-text-input)
|
||||||
|
@ -43,16 +46,19 @@
|
||||||
:else
|
:else
|
||||||
:t/unknown-status-go-error))
|
:t/unknown-status-go-error))
|
||||||
|
|
||||||
(defn account-login-badge [photo-path name]
|
(defn account-login-badge [photo-path name public-key]
|
||||||
[react/view styles/login-badge
|
[react/view styles/login-badge
|
||||||
[photos/photo photo-path {:size styles/login-badge-image-size}]
|
[photos/photo photo-path {:size styles/login-badge-image-size}]
|
||||||
[react/view
|
[react/view
|
||||||
[react/text {:style styles/login-badge-name
|
[react/text {:style styles/login-badge-name
|
||||||
:numberOfLines 1}
|
:ellipsize-mode :middle
|
||||||
name]]])
|
:numberOfLines 1}
|
||||||
|
name]
|
||||||
|
[react/text {:style styles/login-badge-pubkey}
|
||||||
|
(utils/get-shortened-address public-key)]]])
|
||||||
|
|
||||||
(defview login []
|
(defview login []
|
||||||
(letsubs [{:keys [photo-path name error processing save-password? can-save-password?]} [:accounts/login]
|
(letsubs [{:keys [photo-path name public-key error processing save-password? can-save-password?] :as account} [:accounts/login]
|
||||||
can-navigate-back? [:can-navigate-back?]
|
can-navigate-back? [:can-navigate-back?]
|
||||||
password-text-input (atom nil)
|
password-text-input (atom nil)
|
||||||
sign-in-enabled? [:sign-in-enabled?]
|
sign-in-enabled? [:sign-in-enabled?]
|
||||||
|
@ -62,51 +68,51 @@
|
||||||
[login-toolbar can-navigate-back?]
|
[login-toolbar can-navigate-back?]
|
||||||
[react/scroll-view styles/login-view
|
[react/scroll-view styles/login-view
|
||||||
[react/view styles/login-badge-container
|
[react/view styles/login-badge-container
|
||||||
[account-login-badge photo-path name]
|
[account-login-badge photo-path name public-key]
|
||||||
[react/view {:style styles/password-container
|
[react/view {:style styles/password-container
|
||||||
:important-for-accessibility :no-hide-descendants}
|
:important-for-accessibility :no-hide-descendants}
|
||||||
[text-input/text-input-with-label
|
[text-input/text-input-with-label
|
||||||
{:label (i18n/label :t/password)
|
{:placeholder (i18n/label :t/enter-your-password)
|
||||||
:placeholder (i18n/label :t/password)
|
:ref #(reset! password-text-input %)
|
||||||
:ref #(reset! password-text-input %)
|
:auto-focus (= view-id :login)
|
||||||
:auto-focus (= view-id :login)
|
:accessibility-label :password-input
|
||||||
:on-submit-editing (when sign-in-enabled?
|
:on-submit-editing (when sign-in-enabled?
|
||||||
#(login-account @password-text-input))
|
#(login-account @password-text-input))
|
||||||
:on-change-text #(do
|
:on-change-text #(do
|
||||||
(re-frame/dispatch [:set-in [:accounts/login :password]
|
(re-frame/dispatch [:set-in [:accounts/login :password]
|
||||||
(security/mask-data %)])
|
(security/mask-data %)])
|
||||||
(re-frame/dispatch [:set-in [:accounts/login :error] ""]))
|
(re-frame/dispatch [:set-in [:accounts/login :error] ""]))
|
||||||
:secure-text-entry true
|
:secure-text-entry true
|
||||||
:error (when (not-empty error) (i18n/label (error-key error)))}]]
|
:error (when (not-empty error) (i18n/label (error-key error)))}]]
|
||||||
|
|
||||||
(when-not platform/desktop?
|
(when-not platform/desktop?
|
||||||
;; saving passwords is unavailable on Desktop
|
;; saving passwords is unavailable on Desktop
|
||||||
[react/view {:style styles/save-password-checkbox-container}
|
(if (and platform/android? (not can-save-password?))
|
||||||
(if (and platform/android? (not can-save-password?))
|
;; on Android, there is much more reasons for the password save to be unavailable,
|
||||||
;; on Android, there is much more reasons for the password save to be unavailable,
|
;; so we don't show the checkbox whatsoever but put a label explaining why it happenned.
|
||||||
;; so we don't show the checkbox whatsoever but put a label explaining why it happenned.
|
[react/i18n-text {:style styles/save-password-unavailable-android
|
||||||
[react/i18n-text {:style styles/save-password-unavailable-android
|
:key :save-password-unavailable-android}]
|
||||||
:key :save-password-unavailable-android}]
|
[react/view {:style {:flex-direction :row
|
||||||
[profile.components/settings-switch-item
|
:align-items :center
|
||||||
{:label-kw (if can-save-password?
|
:justify-content :flex-start}}
|
||||||
:t/save-password
|
[checkbox/checkbox {:checked? save-password?
|
||||||
:t/save-password-unavailable)
|
:style {:padding-left 0 :padding-right 10}
|
||||||
:active? can-save-password?
|
:on-value-change #(re-frame/dispatch [:set-in [:accounts/login :save-password?] %])}]
|
||||||
:value save-password?
|
[react/text (i18n/label :t/save-password)]]))]]
|
||||||
:action-fn #(re-frame/dispatch [:set-in [:accounts/login :save-password?] %])}])])]]
|
|
||||||
(when processing
|
(when processing
|
||||||
[react/view styles/processing-view
|
[react/view styles/processing-view
|
||||||
[components/activity-indicator {:animating true}]
|
[components/activity-indicator {:animating true}]
|
||||||
[react/i18n-text {:style styles/sign-you-in :key :sign-you-in}]])
|
[react/i18n-text {:style styles/processing :key :processing}]])
|
||||||
(when-not processing
|
[react/view {:style styles/bottom-button-container}
|
||||||
[react/view {:style styles/bottom-button-container}
|
[components.common/button
|
||||||
(when-not can-navigate-back?
|
{:label (i18n/label :t/access-key)
|
||||||
[components.common/bottom-button
|
:button-style styles/bottom-button
|
||||||
{:label (i18n/label :t/other-accounts)
|
:background? false
|
||||||
:on-press #(re-frame/dispatch [:navigate-to-clean :accounts])}])
|
:on-press #(re-frame/dispatch [:accounts.recover.ui/recover-account-button-pressed])}]
|
||||||
[react/view {:style {:flex 1}}]
|
[components.common/button
|
||||||
[components.common/bottom-button
|
{:label (i18n/label :t/submit)
|
||||||
{:forward? true
|
:button-style styles/bottom-button
|
||||||
:label (i18n/label :t/sign-in)
|
:label-style {:color (if (or (not sign-in-enabled?) processing) colors/gray colors/blue)}
|
||||||
:disabled? (not sign-in-enabled?)
|
:background? true
|
||||||
:on-press #(login-account @password-text-input)}]])]))
|
:disabled? (or (not sign-in-enabled?) processing)
|
||||||
|
:on-press #(login-account @password-text-input)}]]]))
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
|
|
||||||
(def accounts-container
|
(def accounts-container
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:padding-horizontal 16
|
:margin-top 24
|
||||||
:background-color colors/gray-lighter})
|
:margin-bottom 16
|
||||||
|
:justify-content :space-between})
|
||||||
|
|
||||||
(def bottom-actions-container
|
(def bottom-actions-container
|
||||||
{:margin-bottom 16})
|
{:margin-bottom 16})
|
||||||
|
@ -21,17 +22,15 @@
|
||||||
:font-size 17})
|
:font-size 17})
|
||||||
|
|
||||||
(defstyle accounts-list-container
|
(defstyle accounts-list-container
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:margin-top 16
|
:padding-bottom 8})
|
||||||
:margin-bottom 16})
|
|
||||||
|
|
||||||
(defstyle account-view
|
(defstyle account-view
|
||||||
{:background-color :white
|
{:background-color :white
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:align-items :center
|
:align-items :center
|
||||||
:padding-horizontal 16
|
:padding-horizontal 16
|
||||||
:height 64
|
:height 64})
|
||||||
:border-radius 8})
|
|
||||||
|
|
||||||
(def account-badge-text-view
|
(def account-badge-text-view
|
||||||
{:margin-left 16
|
{:margin-left 16
|
||||||
|
@ -39,12 +38,18 @@
|
||||||
:flex-shrink 1})
|
:flex-shrink 1})
|
||||||
|
|
||||||
(def account-badge-text
|
(def account-badge-text
|
||||||
{:font-size 17})
|
{:font-weight "500"})
|
||||||
|
|
||||||
(def account-badge-pub-key-text
|
(def account-badge-pub-key-text
|
||||||
{:font-size 14
|
{:font-family "monospace"
|
||||||
:color colors/gray
|
:color colors/gray})
|
||||||
:margin-top 4})
|
|
||||||
|
(def bottom-button
|
||||||
|
{:padding-horizontal 24
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
(def bottom-button-container
|
(def bottom-button-container
|
||||||
{:margin-top 14
|
{:margin-top 14
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
[status-im.ui.screens.accounts.styles :as styles]
|
[status-im.ui.screens.accounts.styles :as styles]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.ui.components.list.views :as list]
|
[status-im.ui.components.list.views :as list]
|
||||||
[status-im.ui.components.status-bar.view :as status-bar]
|
[status-im.ui.components.status-bar.view :as status-bar]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
|
@ -15,41 +16,39 @@
|
||||||
[status-im.ui.screens.privacy-policy.views :as privacy-policy]))
|
[status-im.ui.screens.privacy-policy.views :as privacy-policy]))
|
||||||
|
|
||||||
(defn account-view [{:keys [address photo-path name public-key keycard-instance-uid]}]
|
(defn account-view [{:keys [address photo-path name public-key keycard-instance-uid]}]
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.login.ui/account-selected address photo-path name])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.login.ui/account-selected address photo-path name public-key])}
|
||||||
[react/view styles/account-view
|
[react/view styles/account-view
|
||||||
[photos/photo photo-path {:size styles/account-image-size}]
|
[photos/photo photo-path {:size styles/account-image-size}]
|
||||||
[react/view styles/account-badge-text-view
|
[react/view styles/account-badge-text-view
|
||||||
[react/view {:flex-direction :row}
|
[react/view {:flex-direction :row}
|
||||||
[react/text {:style styles/account-badge-text
|
[react/text {:style styles/account-badge-text
|
||||||
:numberOfLines 1}
|
:ellipsize-mode :middle
|
||||||
|
:numberOfLines 1}
|
||||||
name]
|
name]
|
||||||
(when keycard-instance-uid
|
(when keycard-instance-uid
|
||||||
[icons/icon :main-icons/keycard {:color colors/blue
|
[icons/icon :main-icons/keycard {:color colors/blue
|
||||||
:container-style {:margin-left 7}}])]
|
:container-style {:margin-left 7}}])]
|
||||||
[react/text {:style styles/account-badge-pub-key-text
|
[react/text {:style styles/account-badge-pub-key-text}
|
||||||
:ellipsize-mode :middle
|
(utils/get-shortened-address public-key)]]
|
||||||
:numberOfLines 1}
|
|
||||||
public-key]]
|
|
||||||
[react/view {:flex 1}]
|
[react/view {:flex 1}]
|
||||||
[icons/icon :main-icons/next {:color (colors/alpha colors/black 0.4)}]]])
|
[icons/icon :main-icons/next {:color (colors/alpha colors/gray 0.4)}]]])
|
||||||
|
|
||||||
(defview accounts []
|
(defview accounts []
|
||||||
(letsubs [accounts [:accounts/accounts]]
|
(letsubs [accounts [:accounts/accounts]]
|
||||||
[react/view styles/accounts-view
|
[react/view styles/accounts-view
|
||||||
[status-bar/status-bar]
|
[status-bar/status-bar]
|
||||||
[toolbar/toolbar nil nil
|
[react/text {:style {:typography :header :margin-top 24 :text-align :center}}
|
||||||
[toolbar/content-title (i18n/label :t/sign-in-to-status)]]
|
(i18n/label :t/unlock)]
|
||||||
[react/view styles/accounts-container
|
[react/view styles/accounts-container
|
||||||
[react/view styles/accounts-list-container
|
[react/view styles/accounts-list-container
|
||||||
[list/flat-list {:data (vals accounts)
|
[list/flat-list {:data (vals accounts)
|
||||||
:key-fn :address
|
:key-fn :address
|
||||||
:render-fn (fn [account] [account-view account])
|
:render-fn (fn [account] [account-view account])}]]
|
||||||
:separator [react/view {:height 12}]}]]
|
|
||||||
[react/view
|
[react/view
|
||||||
[components.common/button {:on-press #(re-frame/dispatch [:accounts.create.ui/create-new-account-button-pressed])
|
[components.common/button {:on-press #(re-frame/dispatch [:accounts.create.ui/create-new-account-button-pressed])
|
||||||
:label (i18n/label :t/create-new-account)}]
|
:button-style styles/bottom-button
|
||||||
|
:label (i18n/label :t/generate-a-new-key)}]
|
||||||
[react/view styles/bottom-button-container
|
[react/view styles/bottom-button-container
|
||||||
[components.common/button {:on-press #(re-frame/dispatch [:accounts.recover.ui/recover-account-button-pressed])
|
[components.common/button {:on-press #(re-frame/dispatch [:accounts.recover.ui/recover-account-button-pressed])
|
||||||
:label (i18n/label :t/add-existing-account)
|
:label (i18n/label :t/access-key)
|
||||||
:background? false}]]
|
:background? false}]]]]]))
|
||||||
[privacy-policy/privacy-policy-button]]]]))
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
;; initial state of app-db
|
;; initial state of app-db
|
||||||
(def app-db {:keyboard-height 0
|
(def app-db {:keyboard-height 0
|
||||||
:tab-bar-visible? true
|
:tab-bar-visible? true
|
||||||
:navigation-stack '()
|
:navigation-stack '(:accounts)
|
||||||
:contacts/contacts {}
|
:contacts/contacts {}
|
||||||
:pairing/installations {}
|
:pairing/installations {}
|
||||||
:contact-recovery/pop-up #{}
|
:contact-recovery/pop-up #{}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.react-native.resources :as resources]
|
[status-im.react-native.resources :as resources]
|
||||||
[status-im.privacy-policy.core :as privacy-policy]
|
[status-im.privacy-policy.core :as privacy-policy]
|
||||||
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.accounts.create.core :refer [step-kw-to-num]]
|
[status-im.accounts.create.core :refer [step-kw-to-num]]
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
[status-im.utils.identicon :as identicon]
|
[status-im.utils.identicon :as identicon]
|
||||||
|
@ -76,7 +77,7 @@
|
||||||
:text :intro-text3}] window-width]
|
:text :intro-text3}] window-width]
|
||||||
[react/view styles/buttons-container
|
[react/view styles/buttons-container
|
||||||
[components.common/button {:button-style (assoc styles/bottom-button :margin-bottom 16)
|
[components.common/button {:button-style (assoc styles/bottom-button :margin-bottom 16)
|
||||||
:on-press #(re-frame/dispatch [:accounts.create.ui/intro-wizard])
|
:on-press #(re-frame/dispatch [:accounts.create.ui/intro-wizard true])
|
||||||
:label (i18n/label :t/get-started)}]
|
:label (i18n/label :t/get-started)}]
|
||||||
[components.common/button {:button-style (assoc styles/bottom-button :margin-bottom 24)
|
[components.common/button {:button-style (assoc styles/bottom-button :margin-bottom 24)
|
||||||
:on-press #(re-frame/dispatch [:accounts.recover.ui/recover-account-button-pressed])
|
:on-press #(re-frame/dispatch [:accounts.recover.ui/recover-account-button-pressed])
|
||||||
|
@ -121,10 +122,8 @@
|
||||||
(gfy/generate-gfy (:pubkey acc))]
|
(gfy/generate-gfy (:pubkey acc))]
|
||||||
[react/text {:style (assoc styles/wizard-text
|
[react/text {:style (assoc styles/wizard-text
|
||||||
:text-align :left
|
:text-align :left
|
||||||
:font-family "monospace")
|
:font-family "monospace")}
|
||||||
:number-of-lines 1
|
(utils/get-shortened-address (:pubkey acc))]]
|
||||||
:ellipsize-mode :middle}
|
|
||||||
(:pubkey acc)]]
|
|
||||||
[radio/radio selected?]]]))])
|
[radio/radio selected?]]]))])
|
||||||
|
|
||||||
(defn storage-entry [{:keys [type icon title desc]} selected-storage-type]
|
(defn storage-entry [{:keys [type icon title desc]} selected-storage-type]
|
||||||
|
|
|
@ -72,6 +72,13 @@
|
||||||
:onPress on-accept
|
:onPress on-accept
|
||||||
:accessibility-label :yes-button})))))
|
:accessibility-label :yes-button})))))
|
||||||
|
|
||||||
|
(defn get-shortened-address
|
||||||
|
"Takes first and last 4 digits from address including leading 0x
|
||||||
|
and adds unicode ellipsis in between"
|
||||||
|
[address]
|
||||||
|
(when address
|
||||||
|
(str (subs address 0 6) "\u2026" (subs address (- (count address) 4) (count address)))))
|
||||||
|
|
||||||
;; background-timer
|
;; background-timer
|
||||||
|
|
||||||
(defn set-timeout [cb ms]
|
(defn set-timeout [cb ms]
|
||||||
|
|
|
@ -40,19 +40,16 @@ class TestCreateAccount(SingleDeviceTestCase):
|
||||||
profile.logout()
|
profile.logout()
|
||||||
if sign_in.ok_button.is_element_displayed():
|
if sign_in.ok_button.is_element_displayed():
|
||||||
sign_in.ok_button.click()
|
sign_in.ok_button.click()
|
||||||
sign_in.other_accounts_button.click()
|
sign_in.back_button.click()
|
||||||
sign_in.create_account_button.click()
|
sign_in.generate_new_key_button.click()
|
||||||
sign_in.password_input.set_value(common_password)
|
sign_in.generate_key_button.click()
|
||||||
sign_in.next_button.click()
|
sign_in.next_button.click()
|
||||||
sign_in.confirm_password_input.set_value(common_password)
|
sign_in.next_button.click()
|
||||||
|
sign_in.create_password_input.set_value(common_password)
|
||||||
|
sign_in.next_button.click()
|
||||||
|
sign_in.confirm_your_password_input.set_value(common_password)
|
||||||
sign_in.next_button.click()
|
sign_in.next_button.click()
|
||||||
|
|
||||||
sign_in.element_by_text_part('Display name').wait_for_element(60)
|
|
||||||
username = 'user_%s' % get_current_time()
|
|
||||||
sign_in.name_input.set_value(username)
|
|
||||||
|
|
||||||
sign_in.next_button.click()
|
|
||||||
sign_in.get_started_button.click()
|
|
||||||
if sign_in.get_public_key() == public_key:
|
if sign_in.get_public_key() == public_key:
|
||||||
pytest.fail('New account was not created')
|
pytest.fail('New account was not created')
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,7 @@ class SendTransactionView(BaseView):
|
||||||
def sign_transaction(self, sender_password: str = common_password):
|
def sign_transaction(self, sender_password: str = common_password):
|
||||||
self.sign_with_password.click()
|
self.sign_with_password.click()
|
||||||
self.enter_password_input.send_keys(sender_password)
|
self.enter_password_input.send_keys(sender_password)
|
||||||
self.sign_button.click()
|
self.sign_button.click_until_presence_of_element(self.ok_button)
|
||||||
self.ok_button.click()
|
self.ok_button.click()
|
||||||
|
|
||||||
def get_transaction_fee_total(self):
|
def get_transaction_fee_total(self):
|
||||||
|
|
|
@ -14,6 +14,12 @@ class AccountButton(BaseButton):
|
||||||
class PasswordInput(BaseEditBox):
|
class PasswordInput(BaseEditBox):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(PasswordInput, self).__init__(driver)
|
super(PasswordInput, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.accessibility_id("password-input")
|
||||||
|
|
||||||
|
|
||||||
|
class RecoverAccountPasswordInput(BaseEditBox):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(RecoverAccountPasswordInput, self).__init__(driver)
|
||||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Password']"
|
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Password']"
|
||||||
"/following-sibling::android.view.ViewGroup/android.widget.EditText")
|
"/following-sibling::android.view.ViewGroup/android.widget.EditText")
|
||||||
|
|
||||||
|
@ -36,7 +42,7 @@ class SignInButton(BaseButton):
|
||||||
|
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(SignInButton, self).__init__(driver)
|
super(SignInButton, self).__init__(driver)
|
||||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Sign in' or @text='SIGN IN']")
|
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Sign in' or @text='Submit']")
|
||||||
|
|
||||||
def navigate(self):
|
def navigate(self):
|
||||||
from views.home_view import HomeView
|
from views.home_view import HomeView
|
||||||
|
@ -66,6 +72,12 @@ class GenerateKeyButton(BaseButton):
|
||||||
self.locator = self.Locator.xpath_selector("//*[@text='Generate a key']")
|
self.locator = self.Locator.xpath_selector("//*[@text='Generate a key']")
|
||||||
|
|
||||||
|
|
||||||
|
class GenerateNewKeyButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(GenerateNewKeyButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//*[@text='Generate a new key']")
|
||||||
|
|
||||||
|
|
||||||
class IHaveAccountButton(RecoverAccessButton):
|
class IHaveAccountButton(RecoverAccessButton):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(IHaveAccountButton, self).__init__(driver)
|
super(IHaveAccountButton, self).__init__(driver)
|
||||||
|
@ -130,6 +142,8 @@ class SignInView(BaseView):
|
||||||
|
|
||||||
self.account_button = AccountButton(self.driver)
|
self.account_button = AccountButton(self.driver)
|
||||||
self.password_input = PasswordInput(self.driver)
|
self.password_input = PasswordInput(self.driver)
|
||||||
|
self.recover_account_password_input = RecoverAccountPasswordInput(self.driver)
|
||||||
|
|
||||||
self.sign_in_button = SignInButton(self.driver)
|
self.sign_in_button = SignInButton(self.driver)
|
||||||
self.recover_access_button = RecoverAccessButton(self.driver)
|
self.recover_access_button = RecoverAccessButton(self.driver)
|
||||||
|
|
||||||
|
@ -138,6 +152,7 @@ class SignInView(BaseView):
|
||||||
self.i_have_account_button = IHaveAccountButton(self.driver)
|
self.i_have_account_button = IHaveAccountButton(self.driver)
|
||||||
self.access_key_button = AccessKeyButton(self.driver)
|
self.access_key_button = AccessKeyButton(self.driver)
|
||||||
self.generate_key_button = GenerateKeyButton(self.driver)
|
self.generate_key_button = GenerateKeyButton(self.driver)
|
||||||
|
self.generate_new_key_button = GenerateNewKeyButton(self.driver)
|
||||||
self.add_existing_account_button = AddExistingAccountButton(self.driver)
|
self.add_existing_account_button = AddExistingAccountButton(self.driver)
|
||||||
self.confirm_password_input = ConfirmPasswordInput(self.driver)
|
self.confirm_password_input = ConfirmPasswordInput(self.driver)
|
||||||
self.create_password_input = CreatePasswordInput(self.driver)
|
self.create_password_input = CreatePasswordInput(self.driver)
|
||||||
|
@ -175,8 +190,8 @@ class SignInView(BaseView):
|
||||||
recover_access_view = self.access_key_button.click()
|
recover_access_view = self.access_key_button.click()
|
||||||
recover_access_view.passphrase_input.click()
|
recover_access_view.passphrase_input.click()
|
||||||
recover_access_view.passphrase_input.set_value(passphrase)
|
recover_access_view.passphrase_input.set_value(passphrase)
|
||||||
recover_access_view.password_input.click()
|
recover_access_view.recover_account_password_input.click()
|
||||||
recover_access_view.password_input.set_value(password)
|
recover_access_view.recover_account_password_input.set_value(password)
|
||||||
recover_access_view.sign_in_button.click_until_presence_of_element(recover_access_view.home_button)
|
recover_access_view.sign_in_button.click_until_presence_of_element(recover_access_view.home_button)
|
||||||
return self.get_home_view()
|
return self.get_home_view()
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
:account/account {:public-key nil}
|
:account/account {:public-key nil}
|
||||||
:push-notifications/stored {"0x04d2e59a7501a7bc5bc8bf973a0ab95d06225e2b0f53d5f6be719d857c579bdc1b809bfbe0e8393343f9a5b63a9a90a1a58329c6d1c286d6929f01aaa5472ca9c2"
|
:push-notifications/stored {"0x04d2e59a7501a7bc5bc8bf973a0ab95d06225e2b0f53d5f6be719d857c579bdc1b809bfbe0e8393343f9a5b63a9a90a1a58329c6d1c286d6929f01aaa5472ca9c2"
|
||||||
"0x045db1fdb16c4721ddf32e892c5156d9c7a7445482b84ccd41131eb7970f9d623629d86763c5c2a542ae372815125c27eb73535d583d3285bdbfa16ba37f42e2de"}}
|
"0x045db1fdb16c4721ddf32e892c5156d9c7a7445482b84ccd41131eb7970f9d623629d86763c5c2a542ae372815125c27eb73535d583d3285bdbfa16ba37f42e2de"}}
|
||||||
:dispatch [:ui/open-login "bd36cd64e2621b054a3b7464ff1b3c4c304880e7" "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX" "Bob"]}
|
:dispatch [:ui/open-login "bd36cd64e2621b054a3b7464ff1b3c4c304880e7" "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX" "Bob" nil]}
|
||||||
(notifications/handle-push-notification-open {:db {:accounts/accounts {"bd36cd64e2621b054a3b7464ff1b3c4c304880e7" {:address "bd36cd64e2621b054a3b7464ff1b3c4c304880e7"
|
(notifications/handle-push-notification-open {:db {:accounts/accounts {"bd36cd64e2621b054a3b7464ff1b3c4c304880e7" {:address "bd36cd64e2621b054a3b7464ff1b3c4c304880e7"
|
||||||
:photo-path "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX"
|
:photo-path "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX"
|
||||||
:name "Bob"
|
:name "Bob"
|
||||||
|
|
|
@ -175,6 +175,8 @@
|
||||||
"intro-wizard-title7": "Enable notifications",
|
"intro-wizard-title7": "Enable notifications",
|
||||||
"intro-wizard-text7": "Status will notify you about new messages. You can edit your notification preferences later in settings",
|
"intro-wizard-text7": "Status will notify you about new messages. You can edit your notification preferences later in settings",
|
||||||
"generate-a-key": "Generate a key",
|
"generate-a-key": "Generate a key",
|
||||||
|
"generate-a-new-key": "Generate a new key",
|
||||||
|
"enter-your-password": "Enter your password...",
|
||||||
"generating-keys": "Generating keys...",
|
"generating-keys": "Generating keys...",
|
||||||
"you-will-need-this-code": "You'll need this code to open Status and sign transactions",
|
"you-will-need-this-code": "You'll need this code to open Status and sign transactions",
|
||||||
"this-device": "This device",
|
"this-device": "This device",
|
||||||
|
@ -186,6 +188,7 @@
|
||||||
"about-key-storage-content": "Status will never access your private key. Be sure to backup your Seed phrase. If you lose your phone it is the only way to access your keys.",
|
"about-key-storage-content": "Status will never access your private key. Be sure to backup your Seed phrase. If you lose your phone it is the only way to access your keys.",
|
||||||
"encrypt-with-password": "Encrypt with password",
|
"encrypt-with-password": "Encrypt with password",
|
||||||
"maybe-later": "Maybe later",
|
"maybe-later": "Maybe later",
|
||||||
|
"unlock": "Unlock",
|
||||||
"not-implemented": "!not implemented",
|
"not-implemented": "!not implemented",
|
||||||
"new-contact": "New contact",
|
"new-contact": "New contact",
|
||||||
"datetime-second": {
|
"datetime-second": {
|
||||||
|
@ -290,7 +293,10 @@
|
||||||
"offline-messaging": "Mailserver",
|
"offline-messaging": "Mailserver",
|
||||||
"currency-display-name-nad": "Namibia Dollar",
|
"currency-display-name-nad": "Namibia Dollar",
|
||||||
"creating-your-account": "Creating your account...",
|
"creating-your-account": "Creating your account...",
|
||||||
"save-password": "Save password until logout",
|
"save-password": "Save password",
|
||||||
|
"submit": "Submit",
|
||||||
|
"recover-key": "Recover key",
|
||||||
|
"processing": "Processing...",
|
||||||
"currency-display-name-kes": "Kenyan Shilling",
|
"currency-display-name-kes": "Kenyan Shilling",
|
||||||
"view-etheremon": "View in Etheremon",
|
"view-etheremon": "View in Etheremon",
|
||||||
"wallet-transaction-fee-details": "Gas limit caps the units of gas spent on the transaction. Gas price sets the price per unit of gas. Increasing gas price can make your transaction faster.",
|
"wallet-transaction-fee-details": "Gas limit caps the units of gas spent on the transaction. Gas price sets the price per unit of gas. Increasing gas price can make your transaction faster.",
|
||||||
|
|
Loading…
Reference in New Issue