From a0f851f5ae10ae96aeae11823a0bd89169aa6120 Mon Sep 17 00:00:00 2001 From: Vitaliy Vlasov Date: Tue, 4 Jun 2019 13:54:07 +0300 Subject: [PATCH] Add fingerprint/notifications screens; UI fixes --- resources/icons/main/bell.svg | 5 + resources/icons/main/fingerprint.svg | 3 + resources/icons/main/keycard-logo.svg | 3 + src/status_im/accounts/create/core.cljs | 20 ++- src/status_im/events.cljs | 14 +- .../ui/components/icons/vector_icons.cljs | 6 + .../ui/components/numpad/styles.cljs | 4 +- src/status_im/ui/components/numpad/views.cljs | 21 ++- src/status_im/ui/screens/intro/views.cljs | 121 ++++++++++-------- src/status_im/utils/utils.cljs | 3 + translations/en.json | 9 +- 11 files changed, 142 insertions(+), 67 deletions(-) create mode 100644 resources/icons/main/bell.svg create mode 100644 resources/icons/main/fingerprint.svg create mode 100644 resources/icons/main/keycard-logo.svg diff --git a/resources/icons/main/bell.svg b/resources/icons/main/bell.svg new file mode 100644 index 00000000000..51230b8af36 --- /dev/null +++ b/resources/icons/main/bell.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/icons/main/fingerprint.svg b/resources/icons/main/fingerprint.svg new file mode 100644 index 00000000000..4012ec9254f --- /dev/null +++ b/resources/icons/main/fingerprint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/icons/main/keycard-logo.svg b/resources/icons/main/keycard-logo.svg new file mode 100644 index 00000000000..ed86568ad9a --- /dev/null +++ b/resources/icons/main/keycard-logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/status_im/accounts/create/core.cljs b/src/status_im/accounts/create/core.cljs index cbc901bf6d5..c058adbe60c 100644 --- a/src/status_im/accounts/create/core.cljs +++ b/src/status_im/accounts/create/core.cljs @@ -17,6 +17,7 @@ [status-im.utils.identicon :as identicon] [status-im.utils.signing-phrase.core :as signing-phrase] [status-im.utils.types :as types] + [status-im.utils.utils :as utils] [taoensso.timbre :as log] [status-im.utils.fx :as fx] [status-im.node.core :as node] @@ -154,6 +155,8 @@ (fx/merge {:db (cond-> (assoc-in db [:intro-wizard :step] (dec step)) (#{4 5} step) (assoc-in [:intro-wizard :key-code] nil) + (= step 4) + (assoc-in [:intro-wizard :encrypt-with-password?] false) (= step 5) (assoc-in [:intro-wizard :confirm-failure?] false))} (navigation/navigate-to-cofx :intro-wizard nil)) @@ -161,7 +164,7 @@ (fx/merge {:db (dissoc db :intro-wizard)} (navigation/navigate-to-clean :intro nil))))) -(fx/defn intro-step-forward [{:keys [db] :as cofx}] +(fx/defn intro-step-forward [{:keys [db] :as cofx} {:keys [skip?] :as opts}] (let [step (get-in db [:intro-wizard :step])] (cond (= step 7) @@ -176,7 +179,9 @@ (assoc-in [:intro-wizard :stored-key-code] (get-in db [:intro-wizard :key-code])) (assoc-in [:intro-wizard :key-code] nil) (assoc-in [:intro-wizard :step] 5))} - :else (fx/merge {:db (assoc-in db [:intro-wizard :step] (inc step))} (navigation/navigate-to-cofx :intro-wizard nil))))) + :else (fx/merge {:db (assoc-in db [:intro-wizard :step] + (inc step))} + (navigation/navigate-to-cofx :intro-wizard nil))))) (re-frame/reg-fx :intro-wizard/new-onboarding (fn [{:keys [n mnemonic-length]}] @@ -204,6 +209,9 @@ (log/info "#on-key-storage-selected" storage-type) {:db (assoc-in db [:intro-wizard :selected-storage-type] storage-type)}) +(fx/defn on-encrypt-with-password-pressed [{:keys [db] :as cofx}] + {:db (assoc-in db [:intro-wizard :encrypt-with-password?] true)}) + (fx/defn on-learn-more-pressed [{:keys [db] :as cofx}] {:db (assoc-in db [:intro-wizard :show-learn-more?] true)}) @@ -223,12 +231,18 @@ confirm-failure? (and (= step 5) (= (count new-key-code) 6) (not= new-key-code stored-key-code))] + (when confirm-failure? + (utils/vibrate)) (fx/merge {:db (-> db (assoc-in [:intro-wizard :key-code] new-key-code) (assoc-in [:intro-wizard :confirm-failure?] confirm-failure?))} (when (and (= (count new-key-code) 6) (not confirm-failure?)) - intro-step-forward)))) + (intro-step-forward {}))))) + +(fx/defn password-symbol-pressed [{:keys [db] :as cofx} symbol] + {:db (update-in db [:intro-wizard :password] str symbol)}) + ;;;; COFX (re-frame/reg-cofx diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index ba6763a9313..8fc463ef75c 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -271,8 +271,8 @@ (handlers/register-handler-fx :intro-wizard/step-forward-pressed - (fn [cofx _] - (accounts.create/intro-step-forward cofx))) + (fn [cofx [_ opts]] + (accounts.create/intro-step-forward cofx opts))) (handlers/register-handler-fx :intro-wizard/code-digit-pressed @@ -298,6 +298,16 @@ :intro-wizard/on-learn-more-pressed (fn [cofx _] (accounts.create/on-learn-more-pressed cofx))) + +(handlers/register-handler-fx + :intro-wizard/on-encrypt-with-password-pressed + (fn [cofx _] + (accounts.create/on-encrypt-with-password-pressed cofx))) + +(handlers/register-handler-fx + :intro-wizard/password-symbol-pressed + (fn [cofx [_ symbol]] + (accounts.create/password-symbol-pressed cofx symbol))) ;; accounts recover module (handlers/register-handler-fx diff --git a/src/status_im/ui/components/icons/vector_icons.cljs b/src/status_im/ui/components/icons/vector_icons.cljs index c96490b7f46..831b858874a 100644 --- a/src/status_im/ui/components/icons/vector_icons.cljs +++ b/src/status_im/ui/components/icons/vector_icons.cljs @@ -40,6 +40,7 @@ :main-icons/arrow-up (js/require "./resources/icons/main/arrow_up.svg") :main-icons/back (js/require "./resources/icons/main/back.svg") :main-icons/backspace (js/require "./resources/icons/main/backspace.svg") + :main-icons/bell (js/require "./resources/icons/main/bell.svg") :main-icons/browser (js/require "./resources/icons/main/browser.svg") :main-icons/browser-home (js/require "./resources/icons/main/browser_home.svg") :main-icons/camera (js/require "./resources/icons/main/camera.svg") @@ -56,6 +57,7 @@ :main-icons/dropdown-up (js/require "./resources/icons/main/dropdown_up.svg") :main-icons/edit (js/require "./resources/icons/main/edit.svg") :main-icons/filter (js/require "./resources/icons/main/filter.svg") + :main-icons/fingerprint (js/require "./resources/icons/main/fingerprint.svg") :main-icons/flash-active (js/require "./resources/icons/main/flash_active.svg") :main-icons/flash-inactive (js/require "./resources/icons/main/flash_inactive.svg") :main-icons/fleet (js/require "./resources/icons/main/mailserver.svg") @@ -66,6 +68,7 @@ :main-icons/in-contacts (js/require "./resources/icons/main/in_contacts.svg") :main-icons/info (js/require "./resources/icons/main/info.svg") :main-icons/keycard (js/require "./resources/icons/main/keycard.svg") + :main-icons/keycard-logo (js/require "./resources/icons/main/keycard-logo.svg") :main-icons/language (js/require "./resources/icons/main/language.svg") :main-icons/link (js/require "./resources/icons/main/link.svg") :main-icons/log-level (js/require "./resources/icons/main/mailserver.svg") @@ -138,6 +141,7 @@ :main-icons/arrow-up (components.svg/slurp-svg "./resources/icons/main/arrow_up.svg") :main-icons/back (components.svg/slurp-svg "./resources/icons/main/back.svg") :main-icons/backspace (components.svg/slurp-svg "./resources/icons/main/backspace.svg") + :main-icons/bell (components.svg/slurp-svg "./resources/icons/main/bell.svg") :main-icons/browser (components.svg/slurp-svg "./resources/icons/main/browser.svg") :main-icons/browser-home (components.svg/slurp-svg "./resources/icons/main/browser_home.svg") :main-icons/camera (components.svg/slurp-svg "./resources/icons/main/camera.svg") @@ -154,6 +158,7 @@ :main-icons/dropdown-up (components.svg/slurp-svg "./resources/icons/main/dropdown_up.svg") :main-icons/edit (components.svg/slurp-svg "./resources/icons/main/edit.svg") :main-icons/filter (components.svg/slurp-svg "./resources/icons/main/filter.svg") + :main-icons/fingerprint (components.svg/slurp-svg "./resources/icons/main/fingerprint.svg") :main-icons/flash-active (components.svg/slurp-svg "./resources/icons/main/flash_active.svg") :main-icons/flash-inactive (components.svg/slurp-svg "./resources/icons/main/flash_inactive.svg") :main-icons/fleet (components.svg/slurp-svg "./resources/icons/main/mailserver.svg") @@ -164,6 +169,7 @@ :main-icons/in-contacts (components.svg/slurp-svg "./resources/icons/main/in_contacts.svg") :main-icons/info (components.svg/slurp-svg "./resources/icons/main/info.svg") :main-icons/keycard (components.svg/slurp-svg "./resources/icons/main/keycard.svg") + :main-icons/keycard-logo (components.svg/slurp-svg "./resources/icons/main/keycard-logo.svg") :main-icons/language (components.svg/slurp-svg "./resources/icons/main/language.svg") :main-icons/link (components.svg/slurp-svg "./resources/icons/main/link.svg") :main-icons/log-level (components.svg/slurp-svg "./resources/icons/main/mailserver.svg") diff --git a/src/status_im/ui/components/numpad/styles.cljs b/src/status_im/ui/components/numpad/styles.cljs index c146cfa6906..ca874870be1 100644 --- a/src/status_im/ui/components/numpad/styles.cljs +++ b/src/status_im/ui/components/numpad/styles.cljs @@ -27,11 +27,11 @@ :min-height 292 :max-height 328}) -(def number-container +(defn number-container [hide-container?] {:width 64 :height 64 :border-radius 32 :justify-content :center :align-items :center - :background-color colors/blue-light}) + :background-color (if hide-container? colors/white colors/blue-light)}) diff --git a/src/status_im/ui/components/numpad/views.cljs b/src/status_im/ui/components/numpad/views.cljs index ac8e75b5208..96071b56b03 100644 --- a/src/status_im/ui/components/numpad/views.cljs +++ b/src/status_im/ui/components/numpad/views.cljs @@ -5,13 +5,20 @@ [status-im.ui.components.react :as react])) (defn number-view - [numpad-symbol {:keys [on-press]}] - [(react/touchable-opacity) - {:on-press #(on-press numpad-symbol)} - [react/view {:style styles/number-container} - (if (= numpad-symbol :remove) - [icons/icon :main-icons/backspace {:color colors/blue}] - [react/text {:style styles/number} numpad-symbol])]]) + [numpad-symbol {:keys [on-press hide-dot?]}] + (let [hide-container? (and (= numpad-symbol ".") hide-dot?) + number-container + [react/view {:style (styles/number-container hide-container?)} + (cond (= numpad-symbol :remove) + [icons/icon :main-icons/backspace {:color colors/blue}] + hide-container? + nil + :else [react/text {:style styles/number} numpad-symbol])]] + (if hide-container? + number-container + [(react/touchable-opacity) + {:on-press #(on-press numpad-symbol)} + number-container]))) (defn number-row [[left middle right] opts] diff --git a/src/status_im/ui/screens/intro/views.cljs b/src/status_im/ui/screens/intro/views.cljs index b08a15dd099..bdfa9798998 100644 --- a/src/status_im/ui/screens/intro/views.cljs +++ b/src/status_im/ui/screens/intro/views.cljs @@ -127,14 +127,16 @@ :border-width 1 :border-color (colors/alpha colors/black 0.1)}}] [react/view {:style {:margin-horizontal 16 :flex 1}} - [react/text {:style styles/account-name - :number-of-lines 1 - :ellipsize-mode :middle} - (gfy/generate-gfy (:pubkey acc))] - [react/text {:style styles/account-address - :number-of-lines 1 - :ellipsize-mode :middle} - (:pubkey acc)]] + [react/view {:style {:justify-content :center}} + [react/text {:style styles/account-name + :number-of-lines 1 + :ellipsize-mode :middle} + (gfy/generate-gfy (:pubkey acc))]] + [react/view {:style {:justify-content :center}} + [react/text {:style styles/account-address + :number-of-lines 1 + :ellipsize-mode :middle} + (:pubkey acc)]]] [radio/radio selected?]]]))]) (defn select-key-storage [{:keys [accounts selected-storage-type] :as wizard-state}] @@ -143,7 +145,7 @@ :title :this-device :desc :this-device-desc} {:type :advanced - :icon :main-icons/keycard + :icon :main-icons/keycard-logo :title :keycard :desc :keycard-desc}]] [react/view {:style {:margin-top 84}} @@ -157,35 +159,36 @@ [react/touchable-highlight {:on-press #(re-frame/dispatch [:intro-wizard/on-key-storage-selected type])} [react/view {:style {:flex-direction :row - :align-items :center + :align-items :flex-start :padding-left 16 :padding-right 10 - :margin-top 4 :margin-bottom 30 :background-color (if selected? colors/blue-light colors/white) - :padding-vertical 10}} - - [react/view {:style {:align-self :flex-start}} - [vector-icons/icon icon {:color (if selected? colors/blue colors/gray)}]] + :padding-vertical 16}} + [vector-icons/icon icon {:color (if selected? colors/blue colors/gray)}] [react/view {:style {:margin-horizontal 16 :flex 1}} - [react/text {:style styles/account-name - :number-of-lines 2 - :ellipsize-mode :middle} + [react/text {:style styles/account-name} (i18n/label title)] - [react/text {:style styles/account-address - :number-of-lines 2 - :ellipsize-mode :middle} + [react/text {:style styles/account-address} (i18n/label desc)]] [radio/radio selected?]]]]))])) -(defn create-code [{:keys [key-code] :as wizard-state}] - (let [selected (into (hash-set) (range (count key-code))) - _ (log/info "key-code" key-code)] - [react/view - [react/view {:style {:margin-bottom 32 :align-items :center}} - [dots-selector {:n 6 :selected selected :color colors/blue}]] - [numpad/number-pad {:on-press #(re-frame/dispatch [:intro-wizard/code-digit-pressed %])}] - [react/text {:style styles/wizard-bottom-note} (i18n/label :t/you-will-need-this-code)]])) +(defn create-code [{:keys [key-code encrypt-with-password?] :as wizard-state}] + (let [selected (into (hash-set) (range (count key-code)))] + (if encrypt-with-password? + [react/view + [react/text-input {:secure-text-entry true + :style {:font-size 20 + :line-height 24 + :font-weight "600"} + :on-key-press #(re-frame/dispatch [:intro-wizard/password-symbol-pressed (-> % :nativeEvent :key)])}] + [react/text {:style styles/wizard-bottom-note} (i18n/label :t/password-description)]] + [react/view + [react/view {:style {:margin-bottom 32 :align-items :center}} + [dots-selector {:n 6 :selected selected :color colors/blue}]] + [numpad/number-pad {:on-press #(re-frame/dispatch [:intro-wizard/code-digit-pressed %]) + :hide-dot? true}] + [react/text {:style styles/wizard-bottom-note} (i18n/label :t/you-will-need-this-code)]]))) (defn confirm-code [{:keys [key-code confirm-failure?] :as wizard-state}] (log/info "confirm-code" key-code) @@ -201,27 +204,37 @@ [numpad/number-pad {:on-press #(re-frame/dispatch [:intro-wizard/code-digit-pressed %])}] [react/text {:style styles/wizard-bottom-note} (i18n/label :t/you-will-need-this-code)]])) -(defn enable-fingerprint []) +(defn enable-fingerprint [] + [vector-icons/icon :main-icons/fingerprint {:container-style {:align-items :center :justify-content :center} + :color colors/blue}]) -(defn enable-notifications []) +(defn enable-notifications [] + [vector-icons/icon :main-icons/bell {:container-style {:align-items :center :justify-content :center} + :color colors/white}]) -(defn bottom-bar [{:keys [step generating-keys?] :as wizard-state}] +(defn bottom-bar [{:keys [step generating-keys? encrypt-with-password?] :as wizard-state}] [react/view {:style {:margin-bottom 32}} (cond generating-keys? [react/activity-indicator {:animating true :size :large}] - (= step 1) - [components.common/button {:button-style styles/intro-button - ;:disabled? disable-button? - :on-press #(re-frame/dispatch - [:intro-wizard/step-forward-pressed]) - :label (i18n/label :generate-a-key)}] - (#{4 5} step) + (#{1 6 7} step) + (let [label-kw (case step + 1 :generate-a-key + 6 :intro-wizard-title6 + 7 :intro-wizard-title7)] + [components.common/button {:button-style styles/intro-button + ;:disabled? disable-button? + :on-press #(re-frame/dispatch + [:intro-wizard/step-forward-pressed]) + :label (i18n/label label-kw)}]) + (and (#{4 5} step) + (not encrypt-with-password?)) [react/view (assoc styles/bottom-button-container :align-items :center) - [components.common/button {:button-style styles/bottom-button - :label (i18n/label :t/encrypt-with-password) - :on-press #(re-frame/dispatch [:intro-wizard/on-encrypt-with-password-pressed]) - :background? false}]] + (when-not encrypt-with-password? + [components.common/button {:button-style styles/bottom-button + :label (i18n/label :t/encrypt-with-password) + :on-press #(re-frame/dispatch [:intro-wizard/on-encrypt-with-password-pressed]) + :background? false}])] :else [react/view {:style {:flex-direction :row @@ -233,15 +246,23 @@ [components.common/bottom-button {:on-press #(re-frame/dispatch [:intro-wizard/step-forward-pressed]) :forward? true}]]) - (when (= 1 step) - [react/text {:style styles/wizard-bottom-note} - (i18n/label (if generating-keys? :t/generating-keys :t/this-will-take-few-seconds))])]) + (when (#{1 6 7} step) + [react/text (cond-> {:style styles/wizard-bottom-note} + (#{6 7} step) + (assoc :on-press #(re-frame/dispatch + [:intro-wizard/step-forward-pressed {:skip? true}]))) + (i18n/label (cond generating-keys? :t/generating-keys + (= step 1) + :t/this-will-take-few-seconds + :else :t/maybe-later))])]) -(defn top-bar [step] +(defn top-bar [{:keys [step encrypt-with-password?]}] [react/view {:style {:margin-top 16 :margin-horizontal 32}} - [react/text {:style styles/wizard-title} (i18n/label (keyword (str "intro-wizard-title" step)))] + [react/text {:style styles/wizard-title} + (i18n/label (keyword (str "intro-wizard-title" (when (and (#{4 5} step) encrypt-with-password?) + "-alt") step)))] (cond (#{2 3} step) [react/nested-text {:style styles/wizard-text} (str (i18n/label (keyword (str "intro-wizard-text" step))) " ") @@ -250,7 +271,7 @@ :content (i18n/label (if (= step 2) :t/about-names-content :t/about-key-storage-content))}]) :style {:color colors/blue}} (i18n/label :learn-more)]] - (not= step 5) + (or (not (#{4 5} step)) (and (= 4 step) (not encrypt-with-password?))) [react/text {:style styles/wizard-text} (i18n/label (keyword (str "intro-wizard-text" step)))] :else nil)]) @@ -266,7 +287,7 @@ nil] [react/view {:style {:flex 1 :justify-content :space-between}} - [top-bar step] + [top-bar wizard-state] (do (log/info "#wizard-state" wizard-state) (case step diff --git a/src/status_im/utils/utils.cljs b/src/status_im/utils/utils.cljs index b6610604b0a..bcfa70529f6 100644 --- a/src/status_im/utils/utils.cljs +++ b/src/status_im/utils/utils.cljs @@ -19,6 +19,9 @@ (when on-dismiss (clj->js {:cancelable false}))))) +(defn vibrate [] + (.vibrate (.-Vibration rn-dependencies/react-native))) + (re-frame/reg-fx :utils/show-popup (fn [{:keys [title content on-dismiss]}] diff --git a/translations/en.json b/translations/en.json index 30cf7949b64..a3ecf97d54f 100644 --- a/translations/en.json +++ b/translations/en.json @@ -165,12 +165,14 @@ "intro-wizard-title3": "Select key storage", "intro-wizard-text3": "Your key is stored locally. There is no copy. Only you have access.", "intro-wizard-title4": "Create a 6-digit code", + "intro-wizard-title-alt4": "Create a password", "intro-wizard-text4": "To secure and encrypt your key", "intro-wizard-title5": "Confirm the code", + "intro-wizard-title-alt5": "Confirm your password", "intro-wizard-title6": "Enable fingerprint", "intro-wizard-text6": "Make it easy to sign and send transactions by enambling fingerprint signing", "intro-wizard-title7": "Enable notifications", - "intro-wizard-text7": "Status will notify you about new messages and transactions. 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", "generating-keys": "Generating keys...", "you-will-need-this-code": "You'll need this code to open Status and sign transactions", @@ -180,8 +182,9 @@ "about-names-title": "About the names", "about-names-content": "Your identity is secure and private by design. You get a locally generated cryptographic keypair. The name and image are a readable version of this. They are unique. Nobody can pretend to be you. Nobody sees your name unless you provide it.", "about-key-storage-title": "About key storage", - "about-key-storage-content": "Status will never access your private key. Be sure to backup your Seed phrase. If you loose 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", + "maybe-later": "Maybe later", "not-implemented": "!not implemented", "new-contact": "New contact", "datetime-second": { @@ -679,7 +682,7 @@ "wallet-asset": "Asset", "close-app-content": "The app will stop and close. When you reopen it, the selected network will be used", "logout-app-content": "The account will be logged out. When you log in again, the selected network will be used", - "password-description": "You'll need this password to open the app and confirm transactions.", + "password-description": "At least 6 characters. You'll need this password to open Status and confirm transactions", "currency-display-name-afn": "Afghanistan Afghani", "word-n-description": "In order to check if you have backed up your recovery phrase correctly, enter the word #{{number}} above.", "topic-name-error": "Use only lowercase letters (a to z), numbers & dashes (-). Do not use contact codes",