Onboarding sign-in

Signed-off-by: Vitaliy Vlasov <siphiuel@gmail.com>
This commit is contained in:
Vitaliy Vlasov 2019-07-09 14:37:18 +03:00
parent b78bb456a4
commit 433f840f76
No known key found for this signature in database
GPG Key ID: A7D57C347F2B2964
19 changed files with 189 additions and 130 deletions

View File

@ -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"}
) )

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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}]

View File

@ -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"

View File

@ -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})

View File

@ -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%"

View File

@ -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)}]]]))

View File

@ -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

View File

@ -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]]]]))

View File

@ -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 #{}

View File

@ -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]

View File

@ -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]

View File

@ -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')

View File

@ -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):

View File

@ -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()

View File

@ -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"

View File

@ -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.",