diff --git a/src/quo/components/list_items/quiz_item/view.cljs b/src/quo/components/list_items/quiz_item/view.cljs index 1aef7b8347..3bfa1d58bd 100644 --- a/src/quo/components/list_items/quiz_item/view.cljs +++ b/src/quo/components/list_items/quiz_item/view.cljs @@ -9,8 +9,10 @@ [utils.i18n :as i18n])) (defn- view-internal - [{:keys [state theme number word] :as props}] - [rn/view {:style (style/container props)} + [{:keys [state theme number word on-press] :as props}] + [rn/pressable + {:style (style/container props) + :on-press on-press} (if (or (= state :empty) (= state :disabled)) [rn/view {:style (style/num-container props) diff --git a/src/status_im/contexts/wallet/common/temp.cljs b/src/status_im/contexts/wallet/common/temp.cljs index 9b9326b7d2..9bd2178237 100644 --- a/src/status_im/contexts/wallet/common/temp.cljs +++ b/src/status_im/contexts/wallet/common/temp.cljs @@ -74,3 +74,6 @@ (def secret-phrase ["witch" "collapse" "practice" "feed" "shame" "open" "lion" "collapse" "umbrella" "fabric" "sadness" "obligue"]) +(def random-words + ["cousin" "roof" "minute" "swallow" "wing" "motion" "stomach" + "abuse" "banner" "noble" "poet" "wrist"]) diff --git a/src/status_im/contexts/wallet/create_account/backup_recovery_phrase/style.cljs b/src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/style.cljs similarity index 94% rename from src/status_im/contexts/wallet/create_account/backup_recovery_phrase/style.cljs rename to src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/style.cljs index b094592947..70cc607bd9 100644 --- a/src/status_im/contexts/wallet/create_account/backup_recovery_phrase/style.cljs +++ b/src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/style.cljs @@ -1,4 +1,4 @@ -(ns status-im.contexts.wallet.create-account.backup-recovery-phrase.style +(ns status-im.contexts.wallet.create-account.new-keypair.backup-recovery-phrase.style (:require [quo.foundations.colors :as colors] [quo.theme :as quo.theme] diff --git a/src/status_im/contexts/wallet/create_account/backup_recovery_phrase/view.cljs b/src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/view.cljs similarity index 91% rename from src/status_im/contexts/wallet/create_account/backup_recovery_phrase/view.cljs rename to src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/view.cljs index 4444821de4..c0faf960c5 100644 --- a/src/status_im/contexts/wallet/create_account/backup_recovery_phrase/view.cljs +++ b/src/status_im/contexts/wallet/create_account/new_keypair/backup_recovery_phrase/view.cljs @@ -1,4 +1,4 @@ -(ns status-im.contexts.wallet.create-account.backup-recovery-phrase.view +(ns status-im.contexts.wallet.create-account.new-keypair.backup-recovery-phrase.view (:require [quo.core :as quo] [quo.theme :as quo.theme] @@ -6,7 +6,7 @@ [react-native.core :as rn] [reagent.core :as reagent] [status-im.contexts.wallet.common.temp :as temp] - [status-im.contexts.wallet.create-account.backup-recovery-phrase.style :as style] + [status-im.contexts.wallet.create-account.new-keypair.backup-recovery-phrase.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -80,7 +80,8 @@ {:button-one-label (i18n/label :t/i-have-written) :button-one-props {:disabled? (some false? (vals @checked?)) :customization-color customization-color - :on-press #(js/alert "To be implemented")}}] + :on-press #(rf/dispatch [:navigate-to + :wallet-check-your-backup])}}] [quo/text {:size :paragraph-2 :style (style/description-text theme)} diff --git a/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/style.cljs b/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/style.cljs new file mode 100644 index 0000000000..c1d04d566e --- /dev/null +++ b/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/style.cljs @@ -0,0 +1,28 @@ +(ns status-im.contexts.wallet.create-account.new-keypair.check-your-backup.style) + +(def header-container + {:margin-horizontal 20 + :margin-vertical 12}) + +(def buttons-container + {:padding-horizontal 20 + :padding-vertical 12 + :position :absolute + :bottom 0 + :left 0 + :right 0}) + +(defn buttons-inner-container + [margin-bottom] + {:flex-direction :row + :margin-bottom margin-bottom}) + +(defn button + [margin-right] + {:flex 0.5 + :margin-right margin-right}) + +(def cheat-description + {:padding-horizontal 20 + :padding-top 4 + :padding-bottom 8}) diff --git a/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/view.cljs b/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/view.cljs new file mode 100644 index 0000000000..b20ee05cef --- /dev/null +++ b/src/status_im/contexts/wallet/create_account/new_keypair/check_your_backup/view.cljs @@ -0,0 +1,127 @@ +(ns status-im.contexts.wallet.create-account.new-keypair.check-your-backup.view + (:require + [quo.core :as quo] + [quo.theme :as quo.theme] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im.contexts.wallet.common.temp :as temp] + [status-im.contexts.wallet.create-account.new-keypair.check-your-backup.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(def secret-words-count 12) + +(def questions-count 4) + +(defn- random-selection + [] + (->> (range secret-words-count) + (shuffle) + (take questions-count) + vec)) + +(defn- random-words-with-string + [words given-string] + (let [random-words (->> words + (remove #(= % given-string)) + (shuffle) + (take (dec questions-count))) + result (shuffle (conj random-words given-string))] + [(subvec result 0 2) (subvec result 2 4)])) + +(defn- cheat-warning + [] + (let [{:keys [customization-color]} (rf/sub [:profile/profile])] + [:<> + [quo/drawer-top {:title (i18n/label :t/do-not-cheat)}] + [quo/text + {:style style/cheat-description} + (i18n/label :t/do-not-cheat-description)] + [quo/bottom-actions + {:button-one-label (i18n/label :t/see-recovery-phrase-again) + :button-one-props {:customization-color customization-color + :on-press (fn [] + (rf/dispatch [:hide-bottom-sheet]) + (rf/dispatch [:navigate-back]))}}]])) + +(defn- button + [{:keys [word margin-right on-press]}] + [quo/button + {:type :grey + :on-press #(on-press word) + :container-style (style/button margin-right)} word]) + +(defn- buttons-row + [{:keys [margin-bottom options] :as params}] + [rn/view {:style (style/buttons-inner-container margin-bottom)} + [button + (assoc params + :word (first options) + :margin-right 12)] + [button (assoc params :word (second options))]]) + +(defn- view-internal + [] + (let [random-indices (random-selection) + quiz-index (reagent/atom 0) + incorrect-count (reagent/atom 0) + show-error? (reagent/atom false)] + (fn [] + (let [current-word-index (get random-indices (min @quiz-index (dec questions-count))) + current-word (get temp/secret-phrase current-word-index) + [options-r-0 options-r-1] (random-words-with-string temp/random-words current-word) + on-button-press (fn [word] + (if (= word current-word) + (do + (reset! quiz-index (inc @quiz-index)) + (reset! incorrect-count 0) + (reset! show-error? false)) + (do + (when (> @incorrect-count 0) + (rf/dispatch [:show-bottom-sheet + {:content cheat-warning}])) + (reset! incorrect-count (inc @incorrect-count)) + (reset! show-error? true))))] + [rn/view {:style {:flex 1}} + [quo/page-nav + {:icon-name :i/arrow-left + :on-press #(rf/dispatch [:navigate-back]) + :accessibility-label :top-bar}] + [quo/text-combinations + {:container-style style/header-container + :title (i18n/label :t/check-your-backup) + :description (i18n/label :t/confirm-the-position)}] + [rn/flat-list + {:data random-indices + :render-fn (fn [num index] + [quo/quiz-item + {:state (cond + (and (= @quiz-index index) + (pos? @incorrect-count) + @show-error?) + :error + + (= @quiz-index index) + :empty + + (> @quiz-index index) + :success + + :else + :disabled) + :word (get temp/secret-phrase num) + :number (inc num) + :on-press #(when (= @quiz-index index) + (reset! show-error? false))}]) + :separator [rn/view {:style {:height 8}}] + :content-container-style {:padding-horizontal 20}}] + [rn/view {:style style/buttons-container} + [buttons-row + {:on-press on-button-press + :margin-bottom 12 + :options options-r-0}] + [buttons-row + {:on-press on-button-press + :options options-r-1}]]])))) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 6e04f10e1f..2a3da37c86 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -54,9 +54,11 @@ [status-im.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address-to-watch] [status-im.contexts.wallet.add-address-to-watch.view :as add-address-to-watch] [status-im.contexts.wallet.collectible.view :as wallet-collectible] - [status-im.contexts.wallet.create-account.backup-recovery-phrase.view :as - wallet-backup-recovery-phrase] [status-im.contexts.wallet.create-account.edit-derivation-path.view :as wallet-edit-derivation-path] + [status-im.contexts.wallet.create-account.new-keypair.backup-recovery-phrase.view :as + wallet-backup-recovery-phrase] + [status-im.contexts.wallet.create-account.new-keypair.check-your-backup.view :as + wallet-check-your-backup] [status-im.contexts.wallet.create-account.select-keypair.view :as wallet-select-keypair] [status-im.contexts.wallet.create-account.view :as wallet-create-account] [status-im.contexts.wallet.edit-account.view :as wallet-edit-account] @@ -346,6 +348,10 @@ :options {:insets {:top? true :bottom? true}} :component wallet-backup-recovery-phrase/view} + {:name :wallet-check-your-backup + :options {:insets {:top? true :bottom? true}} + :component wallet-check-your-backup/view} + {:name :wallet-share-address :options options/transparent-screen-options :component wallet-share-address/view} diff --git a/translations/en.json b/translations/en.json index b14dce16f3..9b119a1ae0 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2486,5 +2486,10 @@ "no-routes-found-confirmation": "No routes found. Token type may not be supported or you may don't have enough ETH to cover gas.", "watched-account-removed": "Watched address has been removed", "account-removed": "Account has been removed", - "share-address-title": "{{address}} address" + "share-address-title": "{{address}} address", + "check-your-backup": "Check your backup", + "confirm-the-position": "Confirm the position of certain words in your recovery phrase", + "do-not-cheat": "Don't try to cheat", + "do-not-cheat-description": "These 12 words give access to all of your funds so it is important that you write them in the correct order, take it seriously.", + "see-recovery-phrase-again": "See recovery phrase again" }