[#21573] Keycard - Sign up with a new Keycard

This commit is contained in:
andrey 2024-11-14 12:33:18 +01:00
parent 45cd66f908
commit 16fc393813
No known key found for this signature in database
GPG Key ID: C20F2FDE9A98BA61
6 changed files with 226 additions and 13 deletions

View File

@ -0,0 +1,102 @@
(ns status-im.contexts.keycard.create.events
(:require [clojure.string :as string]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/create.check-empty-card
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.empty-create]))
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(rf/reg-event-fx :keycard/create.get-phrase
(fn [{:keys [db]}]
{:db (assoc-in db [:keycard :create] nil)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:open-modal :screen/backup-recovery-phrase-dark
{:on-success #(rf/dispatch [:keycard/create.phrase-backed-up %])}]]]}))
(rf/reg-event-fx :keycard/create.phrase-backed-up
(fn [{:keys [db]} [masked-phrase-vector]]
{:db (assoc-in db
[:keycard :create :masked-phrase]
(->> masked-phrase-vector
security/safe-unmask-data
(string/join " ")
security/mask-data))
:fx [[:dispatch [:keycard/create.create-or-enter-pin]]]}))
(rf/reg-event-fx :keycard/create.create-or-enter-pin
(fn [{:keys [db]}]
(let [{:keys [initialized?]} (get-in db [:keycard :application-info])]
{:fx [[:dispatch [:navigate-back]]
(if initialized?
[:dispatch
[:open-modal :screen/keycard.pin.enter
{:on-complete (fn [new-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/create.save-pin new-pin])
(rf/dispatch [:open-modal :screen/keycard.create.ready-to-add]))}]]
[:dispatch
[:open-modal :screen/keycard.pin.create
{:on-complete (fn [new-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/create.save-pin new-pin])
(rf/dispatch [:open-modal :screen/keycard.create.ready-to-add]))}]])]})))
(rf/reg-event-fx :keycard/create.save-pin
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :create :pin] pin)}))
(rf/reg-event-fx :keycard/create.start
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(rf/dispatch [:keycard/create.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(defn get-application-info-and-continue
[init?]
(rf/dispatch [:keycard/get-application-info
{:on-success #(rf/dispatch [:keycard/create.continue])
:on-error
(fn [error]
(if (or (= error :keycard/error.keycard-blank)
(and (not init?) (= error :keycard/error.keycard-wrong-profile)))
(rf/dispatch [:keycard/create.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]))
(rf/reg-event-fx :keycard/create.continue
(fn [{:keys [db]}]
(let [{:keys [initialized? has-master-key?]} (get-in db [:keycard :application-info])
{:keys [masked-phrase pin]} (get-in db [:keycard :create])]
(cond
(not initialized?)
{:fx [[:keycard/init-card
{:pin pin
:on-success #(get-application-info-and-continue true)}]]}
(not has-master-key?)
{:fx [[:effects.keycard/generate-and-load-key
{:mnemonic (security/safe-unmask-data masked-phrase)
:pin pin
:on-success #(get-application-info-and-continue false)
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}
:else
{:fx [[:effects.keycard/get-more-keys
{:pin pin
:on-success #(rf/dispatch [:keycard.login/recover-profile-and-login %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}))))

View File

@ -0,0 +1,62 @@
(ns status-im.contexts.keycard.create.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
[:<>
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/create-profile-keycard)}]
[rn/view {:style {:padding-horizontal 20 :padding-top 20}}
[quo/small-option-card
{:variant :main
:title (i18n/label :t/check-keycard)
:subtitle (i18n/label :t/see-keycard-ready)
:button-label (i18n/label :t/scan-keycard)
:accessibility-label :get-keycard
:image (resources/get-image :check-your-keycard)
:on-press #(rf/dispatch [:keycard/create.check-empty-card])}]
[rn/view {:style {:height 12}}]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/learn-more-keycard)
:subtitle (i18n/label :t/secure-wallet-card)
:accessibility-label :setup-keycard
:image (resources/get-image :use-keycard)
:on-press #(rf/dispatch [:browser.ui/open-url constants/get-keycard-url])}]]
[rn/view {:style {:flex 1}}]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]])
(defn ready-to-add
[]
[:<>
[quo/page-nav
{:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/ready-add-keypair-keycard)
:description :text
:description-text ""}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :generate-keys1)}]]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
:button-one-props {:on-press #(rf/dispatch [:keycard/create.start])}}]])

View File

@ -7,6 +7,30 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn create
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-empty)
:description :text
:description-text (i18n/label :t/what-to-do)}]
[rn/view {:style {:padding-horizontal 28 :padding-top 20}}
[quo/small-option-card
{:variant :main
:title (i18n/label :t/create-new-profile)
:subtitle (i18n/label :t/new-key-pair-keycard)
:button-label (i18n/label :t/lets-go)
:accessibility-label :create-new-profile-keycard
:image (resources/get-image :keycard-buy)
:on-press #(rf/dispatch [:keycard/create.get-phrase])}]]
[quo/information-box
{:type :default
:style {:margin-top 32 :margin-horizontal 28}}
(i18n/label :t/add-key-pair-desktop)]])
(defn view
[]
[:<>
@ -23,7 +47,7 @@
:title (i18n/label :t/import-key-pair-keycard)
:subtitle (i18n/label :t/use-keycard-login-sign)
:button-label (i18n/label :t/import-profile-key-pair)
:accessibility-label :get-keycard
:accessibility-label :import-key-pair-keycard
:image (resources/get-image :keycard-buy)
:on-press (fn []
(rf/dispatch

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.keycard.events
(:require [re-frame.core :as rf]
status-im.contexts.keycard.create.events
status-im.contexts.keycard.login.events
status-im.contexts.keycard.migrate.events
status-im.contexts.keycard.migrate.re-encrypting.events

View File

@ -108,17 +108,25 @@
:image (resources/get-image :ethereum-address)
:on-press nav-to-seed-phrase-with-cur-screen}]
[rn/view {:style style/space-between-suboptions}]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/profile-keys-on-keycard)
:accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard)
:on-press (fn []
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press
#(rf/dispatch
[:keycard.login/check-card])}]))}]]]))
(if create-profile?
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle)
:accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard)
:on-press #(rf/dispatch [:open-modal :screen/keycard.create-profile])}]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/profile-keys-on-keycard)
:accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard)
:on-press (fn []
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press
#(rf/dispatch
[:keycard.login/check-card])}]))}])]]))
(defn- navigate-back
[]

View File

@ -30,6 +30,7 @@
[status-im.contexts.communities.overview.view :as communities.overview]
[status-im.contexts.keycard.authorise.view :as keycard.authorise]
[status-im.contexts.keycard.check.view :as keycard.check]
[status-im.contexts.keycard.create.view :as keycard.create]
[status-im.contexts.keycard.empty.view :as keycard.empty]
[status-im.contexts.keycard.error.view :as keycard.error]
[status-im.contexts.keycard.migrate.fail.view :as keycard.migrate.fail]
@ -884,6 +885,11 @@
:insets {:top? true :bottom? true}}
:component keycard.empty/view}
{:name :screen/keycard.empty-create
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.empty/create}
{:name :screen/keycard.error
:metrics {:track? :true}
:options {:theme :dark
@ -951,7 +957,17 @@
:metrics {:track? :true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:component keycard.migrate.profile-keys/view}])
:component keycard.migrate.profile-keys/view}
{:name :screen/keycard.create-profile
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.create/view}
{:name :screen/keycard.create.ready-to-add
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.create/ready-to-add}])
(defn screens
[]