[#21573] Keycard - Sign up with a new Keycard (#21623)

This commit is contained in:
flexsurfer 2024-11-25 15:22:21 +01:00 committed by GitHub
parent 6ec307a8bb
commit 9c9b55fe3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 224 additions and 19 deletions

View File

@ -0,0 +1,101 @@
(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 [:keycard/create.save-pin new-pin])
(rf/dispatch [:keycard/create.start]))}]]
[: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

@ -6,7 +6,6 @@
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.create-or-sync-profile.style :as style]
@ -44,11 +43,6 @@
:screen/onboarding.new-to-status
:screen/onboarding.sync-or-recover-profile)]))
(defn- check-your-keycard
[]
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press #(rf/dispatch [:keycard.login/check-card])}]))
(defn- option-card-max-height
[window-height]
(- window-height
@ -90,16 +84,6 @@
:image (resources/get-image :ethereum-address)
:on-press #(navigate-to-sign-in-by-recovery-phrase true)}])
(defn- use-empty-keycard-icon-card
[]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-an-empty-keycard)
:subtitle (i18n/label :t/use-an-empty-keycard-subtitle)
:accessibility-label :use-an-empty-keycard-icon-card
:image (resources/get-image :use-keycard)
:on-press status-im.common.not-implemented/alert}])
(defn- log-in-by-syncing-icon-card
[]
[quo/small-option-card
@ -110,6 +94,16 @@
:image (resources/get-image :ethereum-address)
:on-press show-check-before-syncing}])
(defn- use-empty-keycard-icon-card
[]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-an-empty-keycard)
:subtitle (i18n/label :t/use-an-empty-keycard-subtitle)
:accessibility-label :use-an-empty-keycard-icon-card
:image (resources/get-image :use-keycard)
:on-press #(rf/dispatch [:open-modal :screen/keycard.create-profile])}])
(defn- log-in-with-keycard-icon-card
[]
[quo/small-option-card
@ -118,7 +112,9 @@
:subtitle (i18n/label :t/log-in-with-keycard-subtitle)
:accessibility-label :log-in-with-keycard
:image (resources/get-image :use-keycard)
:on-press check-your-keycard}])
:on-press (fn []
(rf/dispatch [:open-modal :screen/keycard.check
{:on-press #(rf/dispatch [:keycard.login/check-card])}]))}])
(defn sign-in-options
[create-profile?]

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]
@ -891,6 +892,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
@ -958,7 +964,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
[]

View File

@ -57,6 +57,7 @@
"add-custom-token": "Add custom token",
"add-eth": "Add ETH",
"add-favourite": "Add favourite",
"add-key-pair-desktop": "To add existing key pair to the Keycard please use Status Desktop. If you'd like this feature on mobile, feel free to upvote them.",
"add-mailserver": "Add Status node",
"add-me-to-your-contacts": "Please add me to your contacts",
"add-members": "Add members",
@ -550,6 +551,7 @@
"create-pin": "Create 6-digit passcode",
"create-pin-description": "You'll need your card + this 6-digit passcode to unlock Status and to confirm transactions",
"create-profile": "Create profile",
"create-profile-keycard": "Create profile on empty Keycard",
"create-profile-password-info-box-description": "Your Status keys are the foundation of your self-sovereign identity in Web3. You have complete control over these keys, which you can use to sign transactions, access your data, and interact with Web3 services.\n\nYour keys are always securely stored on your device and protected by your Status profile password. Status doesn't know your password and can't reset it for you. If you forget your password, you may lose access to your Status profile and wallet funds.\n\nRemember your Status password and don't share it with anyone.",
"create-profile-password-info-box-title": "About your profile password",
"created-group-chat-description": "You created the group {{group-name}}",
@ -1430,6 +1432,7 @@
"layer-2": "Layer 2",
"learn-more": "Learn more",
"learn-more-about-keycard": "Learn more about Keycard",
"learn-more-keycard": "Learn more about Keycard",
"leave": "Leave",
"leave-chat": "Leave chat",
"leave-chat-confirmation": "Chat history will be removed from your device. After rejoining you won't be able to retrieve any of your history.",
@ -1708,6 +1711,7 @@
"new-group": "New group",
"new-group-chat": "New group chat",
"new-group-limit": "You can only add {{max-contacts}} contacts to the group chat",
"new-key-pair-keycard": "New key pair will be stored on Keycard",
"new-messages-header": "New Messages",
"new-network": "New network",
"new-password": "New password",
@ -2058,6 +2062,7 @@
"re-encrypting-data": "Re-encrypting data",
"read": "Read",
"read-more": "Read more",
"ready-add-keypair-keycard": "Ready to add key pair to Keycard",
"ready-keycard": "Get your Keycard ready",
"ready-to-migrate-key-pair": "Ready to migrate profile key pair to the Keycard",
"ready-to-scan": "Ready to Scan",