feature #4255 - backup recovery phrase in desktop app
Signed-off-by: Goran Jovic <goranjovic@gmail.com>
This commit is contained in:
parent
5dec44340d
commit
22119ccf27
|
@ -53,11 +53,12 @@
|
||||||
:disabled active?
|
:disabled active?
|
||||||
:on-press #(re-frame/dispatch [:show-desktop-tab view-id])}
|
:on-press #(re-frame/dispatch [:show-desktop-tab view-id])}
|
||||||
[react/view
|
[react/view
|
||||||
[content active? (if (= view-id :home) cnt nil)]]]))
|
[content active? cnt]]]))
|
||||||
|
|
||||||
(views/defview main-tabs []
|
(views/defview main-tabs []
|
||||||
(views/letsubs [current-tab [:get-in [:desktop/desktop :tab-view-id]]]
|
(views/letsubs [current-tab [:get-in [:desktop/desktop :tab-view-id]]]
|
||||||
[react/view
|
[react/view
|
||||||
[react/view {:style tabs.styles/tabs-container}
|
[react/view {:style tabs.styles/tabs-container}
|
||||||
(for [[index {:keys [content view-id count-subscription]}] tabs-list-indexed]
|
(for [[index {:keys [content view-id count-subscription]}] tabs-list-indexed]
|
||||||
^{:key index} [tab index content view-id (= current-tab view-id) count-subscription])]]))
|
^{:key index}
|
||||||
|
[tab index content view-id (= current-tab view-id) count-subscription])]]))
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
(:require-macros [status-im.utils.views :as views])
|
(:require-macros [status-im.utils.views :as views])
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.screens.profile.user.views :as profile]
|
|
||||||
[status-im.utils.build :as build]
|
[status-im.utils.build :as build]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
|
@ -13,7 +12,9 @@
|
||||||
[status-im.ui.screens.offline-messaging-settings.views :as offline-messaging.views]
|
[status-im.ui.screens.offline-messaging-settings.views :as offline-messaging.views]
|
||||||
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
|
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
|
||||||
[status-im.ui.screens.desktop.main.tabs.profile.styles :as styles]
|
[status-im.ui.screens.desktop.main.tabs.profile.styles :as styles]
|
||||||
[status-im.ui.screens.profile.user.views :as profile]))
|
[status-im.ui.screens.profile.user.views :as profile]
|
||||||
|
[status-im.ui.screens.profile.seed.views :as profile.recovery]
|
||||||
|
[status-im.ui.components.common.common :as components.common]))
|
||||||
|
|
||||||
(defn profile-badge [{:keys [name photo-path]} editing?]
|
(defn profile-badge [{:keys [name photo-path]} editing?]
|
||||||
[react/view styles/profile-badge
|
[react/view styles/profile-badge
|
||||||
|
@ -82,6 +83,9 @@
|
||||||
[react/view {:style {:margin-vertical 8}}
|
[react/view {:style {:margin-vertical 8}}
|
||||||
[render-fn node]])]])))
|
[render-fn node]])]])))
|
||||||
|
|
||||||
|
(views/defview backup-recovery-phrase []
|
||||||
|
[profile.recovery/backup-seed])
|
||||||
|
|
||||||
(defn share-contact-code []
|
(defn share-contact-code []
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :qr-code])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :qr-code])}
|
||||||
[react/view {:style styles/share-contact-code}
|
[react/view {:style styles/share-contact-code}
|
||||||
|
@ -92,10 +96,12 @@
|
||||||
:accessibility-label :share-my-contact-code-button}
|
:accessibility-label :share-my-contact-code-button}
|
||||||
[vector-icons/icon :icons/qr {:style {:tint-color colors/blue}}]]]])
|
[vector-icons/icon :icons/qr {:style {:tint-color colors/blue}}]]]])
|
||||||
|
|
||||||
(views/defview profile [user]
|
(views/defview profile [{:keys [seed-backed-up? mnemonic] :as user}]
|
||||||
(views/letsubs [current-view-id [:get :view-id]
|
(views/letsubs [current-view-id [:get :view-id]
|
||||||
editing? [:get :my-profile/editing?]] ;; TODO janherich: refactor my-profile, unnecessary complicated structure in db (could be just `:staged-name`/`:editing?` fields in account map) and horrible way to access it woth `:get`/`:set` subs/events
|
editing? [:get :my-profile/editing?]] ;; TODO janherich: refactor my-profile, unnecessary complicated structure in db (could be just `:staged-name`/`:editing?` fields in account map) and horrible way to access it woth `:get`/`:set` subs/events
|
||||||
(let [adv-settings-open? (= current-view-id :advanced-settings)]
|
(let [adv-settings-open? (= current-view-id :advanced-settings)
|
||||||
|
backup-recovery-phrase-open? (= current-view-id :backup-recovery-phrase)
|
||||||
|
show-backup-seed? (and (not seed-backed-up?) (not (string/blank? mnemonic)))]
|
||||||
[react/view
|
[react/view
|
||||||
[react/view {:style styles/profile-edit}
|
[react/view {:style styles/profile-edit}
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch (if editing?
|
[react/touchable-highlight {:on-press #(re-frame/dispatch (if editing?
|
||||||
|
@ -113,6 +119,14 @@
|
||||||
:font (if adv-settings-open? :medium :default)}
|
:font (if adv-settings-open? :medium :default)}
|
||||||
(i18n/label :t/advanced-settings)]
|
(i18n/label :t/advanced-settings)]
|
||||||
[vector-icons/icon :icons/forward {:style {:tint-color colors/gray}}]]]
|
[vector-icons/icon :icons/forward {:style {:tint-color colors/gray}}]]]
|
||||||
|
(when show-backup-seed?
|
||||||
|
[react/touchable-highlight {:style (styles/profile-row backup-recovery-phrase-open?)
|
||||||
|
:on-press #(re-frame/dispatch [:navigate-to :backup-recovery-phrase])}
|
||||||
|
[react/view {:style styles/adv-settings}
|
||||||
|
[react/text {:style (styles/profile-row-text colors/black)
|
||||||
|
:font (if backup-recovery-phrase-open? :medium :default)}
|
||||||
|
(i18n/label :wallet-backup-recovery-title)]
|
||||||
|
[components.common/counter {:size 22} 1]]])
|
||||||
[react/view {:style (styles/profile-row false)}
|
[react/view {:style (styles/profile-row false)}
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.logout.ui/logout-confirmed])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:accounts.logout.ui/logout-confirmed])}
|
||||||
[react/text {:style (styles/profile-row-text colors/red)} (i18n/label :t/logout)]]
|
[react/text {:style (styles/profile-row-text colors/red)} (i18n/label :t/logout)]]
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
:qr-code profile.views/qr-code
|
:qr-code profile.views/qr-code
|
||||||
:advanced-settings profile.views/advanced-settings
|
:advanced-settings profile.views/advanced-settings
|
||||||
:chat-profile chat.views/chat-profile
|
:chat-profile chat.views/chat-profile
|
||||||
|
:backup-recovery-phrase profile.views/backup-recovery-phrase
|
||||||
status-view)]
|
status-view)]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
[component]])))
|
[component]])))
|
||||||
|
|
|
@ -24,9 +24,11 @@
|
||||||
:contact-toggle-list contact-toggle-list
|
:contact-toggle-list contact-toggle-list
|
||||||
(:new-contact
|
(:new-contact
|
||||||
:advanced-settings
|
:advanced-settings
|
||||||
:chat :home
|
:chat
|
||||||
|
:home
|
||||||
:qr-code
|
:qr-code
|
||||||
:chat-profile) main.views/main-views
|
:chat-profile
|
||||||
|
:backup-recovery-phrase) main.views/main-views
|
||||||
:login login.views/login
|
:login login.views/login
|
||||||
react/view)]
|
react/view)]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
:source source
|
:source source
|
||||||
:value value})))
|
:value value})))
|
||||||
|
|
||||||
(defmethod navigation/preload-data! :backup-seed
|
|
||||||
[db]
|
|
||||||
(assoc db :my-profile/seed {:step :intro}))
|
|
||||||
|
|
||||||
(defmethod navigation/unload-data! :my-profile
|
(defmethod navigation/unload-data! :my-profile
|
||||||
[db]
|
[db]
|
||||||
(dissoc db :my-profile/editing?))
|
(dissoc db :my-profile/editing?))
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
{:flex-direction :row})
|
{:flex-direction :row})
|
||||||
|
|
||||||
(def six-word-num
|
(def six-word-num
|
||||||
{:width 20
|
{:width 25
|
||||||
:text-align :right
|
:text-align :right
|
||||||
:opacity 0.4
|
:opacity 0.4
|
||||||
:font-size 15
|
:font-size 15
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.ui.screens.profile.seed.styles :as styles]
|
[status-im.ui.screens.profile.seed.styles :as styles]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.styles :as common.styles]))
|
[status-im.ui.components.styles :as common.styles]
|
||||||
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(def steps-numbers
|
(def steps-numbers
|
||||||
{:intro 1
|
{:intro 1
|
||||||
|
@ -36,8 +37,9 @@
|
||||||
|
|
||||||
(defn intro []
|
(defn intro []
|
||||||
[react/view {:style styles/intro-container}
|
[react/view {:style styles/intro-container}
|
||||||
|
(when-not platform/desktop?
|
||||||
[components.common/image-contain {:container-style styles/intro-image}
|
[components.common/image-contain {:container-style styles/intro-image}
|
||||||
(:lock resources/ui)]
|
(:lock resources/ui)])
|
||||||
[react/i18n-text {:style styles/intro-text
|
[react/i18n-text {:style styles/intro-text
|
||||||
:key :your-data-belongs-to-you}]
|
:key :your-data-belongs-to-you}]
|
||||||
[react/i18n-text {:style styles/intro-description
|
[react/i18n-text {:style styles/intro-description
|
||||||
|
@ -80,7 +82,7 @@
|
||||||
{:forward? true
|
{:forward? true
|
||||||
:on-press #(re-frame/dispatch [:my-profile/enter-two-random-words])}]]]))
|
:on-press #(re-frame/dispatch [:my-profile/enter-two-random-words])}]]]))
|
||||||
|
|
||||||
(defview input [error]
|
(defview input [error next-handler]
|
||||||
(letsubs [ref (reagent/atom nil)]
|
(letsubs [ref (reagent/atom nil)]
|
||||||
{:component-did-mount (fn [_] (when config/testfairy-enabled?
|
{:component-did-mount (fn [_] (when config/testfairy-enabled?
|
||||||
(.hideView js-dependencies/testfairy @ref)))}
|
(.hideView js-dependencies/testfairy @ref)))}
|
||||||
|
@ -89,26 +91,11 @@
|
||||||
:ref (partial reset! ref)
|
:ref (partial reset! ref)
|
||||||
:auto-focus true
|
:auto-focus true
|
||||||
:on-change-text #(re-frame/dispatch [:set-in [:my-profile/seed :word] %])
|
:on-change-text #(re-frame/dispatch [:set-in [:my-profile/seed :word] %])
|
||||||
|
:on-submit-editing next-handler
|
||||||
:error error}]))
|
:error error}]))
|
||||||
|
|
||||||
(defn enter-word [step [idx word] error entered-word]
|
(defn next-handler [word entered-word step]
|
||||||
^{:key word}
|
(fn [_]
|
||||||
[react/view {:style styles/enter-word-container}
|
|
||||||
[react/view {:style styles/enter-word-row}
|
|
||||||
[react/text {:style styles/enter-word-label}
|
|
||||||
(i18n/label :t/check-your-recovery-phrase)]
|
|
||||||
[react/text {:style styles/enter-word-n}
|
|
||||||
(i18n/label :t/word-n {:number (inc idx)})]]
|
|
||||||
[input error]
|
|
||||||
[react/text {:style styles/enter-word-n-description}
|
|
||||||
(i18n/label :t/word-n-description {:number (inc idx)})]
|
|
||||||
[react/view styles/twelve-words-spacer]
|
|
||||||
[react/view styles/twelve-words-button-container
|
|
||||||
[components.common/bottom-button
|
|
||||||
{:forward? (not= :second-word step)
|
|
||||||
:label (when (= :second-word step) (i18n/label :t/done))
|
|
||||||
:disabled? (string/blank? entered-word)
|
|
||||||
:on-press (fn [_]
|
|
||||||
(cond (not= word entered-word)
|
(cond (not= word entered-word)
|
||||||
(re-frame/dispatch [:set-in [:my-profile/seed :error] (i18n/label :t/wrong-word)])
|
(re-frame/dispatch [:set-in [:my-profile/seed :error] (i18n/label :t/wrong-word)])
|
||||||
|
|
||||||
|
@ -119,7 +106,26 @@
|
||||||
(utils/show-question
|
(utils/show-question
|
||||||
(i18n/label :t/are-you-sure?)
|
(i18n/label :t/are-you-sure?)
|
||||||
(i18n/label :t/are-you-sure-description)
|
(i18n/label :t/are-you-sure-description)
|
||||||
#(re-frame/dispatch [:my-profile/finish]))))}]]])
|
#(re-frame/dispatch [:my-profile/finish])))))
|
||||||
|
|
||||||
|
(defn enter-word [step [idx word] error entered-word]
|
||||||
|
^{:key word}
|
||||||
|
[react/view {:style styles/enter-word-container}
|
||||||
|
[react/view {:style styles/enter-word-row}
|
||||||
|
[react/text {:style styles/enter-word-label}
|
||||||
|
(i18n/label :t/check-your-recovery-phrase)]
|
||||||
|
[react/text {:style styles/enter-word-n}
|
||||||
|
(i18n/label :t/word-n {:number (inc idx)})]]
|
||||||
|
[input error (next-handler word entered-word step)]
|
||||||
|
[react/text {:style styles/enter-word-n-description}
|
||||||
|
(i18n/label :t/word-n-description {:number (inc idx)})]
|
||||||
|
[react/view styles/twelve-words-spacer]
|
||||||
|
[react/view styles/twelve-words-button-container
|
||||||
|
[components.common/bottom-button
|
||||||
|
{:forward? (not= :second-word step)
|
||||||
|
:label (when (= :second-word step) (i18n/label :t/done))
|
||||||
|
:disabled? (string/blank? entered-word)
|
||||||
|
:on-press (next-handler word entered-word step)}]]])
|
||||||
|
|
||||||
(defn finish []
|
(defn finish []
|
||||||
[react/view {:style styles/finish-container}
|
[react/view {:style styles/finish-container}
|
||||||
|
@ -136,12 +142,12 @@
|
||||||
|
|
||||||
(defview backup-seed []
|
(defview backup-seed []
|
||||||
(letsubs [current-account [:get-current-account]
|
(letsubs [current-account [:get-current-account]
|
||||||
{:keys [step first-word second-word error word]} [:get :my-profile/seed]]
|
{:keys [step first-word second-word error word]} [:my-profile/recovery]]
|
||||||
[react/keyboard-avoiding-view {:style styles/backup-seed-container}
|
[react/keyboard-avoiding-view {:style styles/backup-seed-container}
|
||||||
[status-bar/status-bar]
|
[status-bar/status-bar]
|
||||||
[toolbar/toolbar
|
[toolbar/toolbar
|
||||||
nil
|
nil
|
||||||
(when-not (#{:finish} step)
|
(when-not (= :finish step)
|
||||||
(toolbar/nav-button (actions/back #(step-back step))))
|
(toolbar/nav-button (actions/back #(step-back step))))
|
||||||
[react/view
|
[react/view
|
||||||
[react/text {:style styles/backup-seed}
|
[react/text {:style styles/backup-seed}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
(ns status-im.ui.screens.profile.subs
|
(ns status-im.ui.screens.profile.subs
|
||||||
(:require [re-frame.core :refer [reg-sub]]
|
(:require [re-frame.core :as re-frame]
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[status-im.utils.build :as build]
|
[status-im.utils.build :as build]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(reg-sub
|
(re-frame/reg-sub
|
||||||
:get-profile-unread-messages-number
|
:get-profile-unread-messages-number
|
||||||
:<- [:get-current-account]
|
:<- [:get-current-account]
|
||||||
(fn [{:keys [seed-backed-up? mnemonic]}]
|
(fn [{:keys [seed-backed-up? mnemonic]}]
|
||||||
(if (or seed-backed-up? (string/blank? mnemonic)) 0 1)))
|
(if (or seed-backed-up? (string/blank? mnemonic)) 0 1)))
|
||||||
|
|
||||||
(reg-sub
|
(re-frame/reg-sub
|
||||||
:get-app-version
|
:get-app-version
|
||||||
(fn [{:keys [web3-node-version]}]
|
(fn [{:keys [web3-node-version]}]
|
||||||
(let [version (if platform/desktop? build/version build/build-no)]
|
(let [version (if platform/desktop? build/version build/build-no)]
|
||||||
(str build/version " (" version "); node " (or web3-node-version "N/A") ""))))
|
(str build/version " (" version "); node " (or web3-node-version "N/A") ""))))
|
||||||
|
|
||||||
(reg-sub :get-device-UUID
|
(re-frame/reg-sub
|
||||||
|
:get-device-UUID
|
||||||
(fn [db]
|
(fn [db]
|
||||||
(:device-UUID db)))
|
(:device-UUID db)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:my-profile/recovery
|
||||||
|
(fn [db]
|
||||||
|
(or (:my-profile/seed db) {:step :intro})))
|
||||||
|
|
Loading…
Reference in New Issue