diff --git a/package.json b/package.json index 5681f8311d..34e68d2086 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "react-native-screens": "^2.10.1", "react-native-shake": "^3.3.1", "react-native-splash-screen": "^3.2.0", - "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.31", + "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.32", "react-native-svg": "^9.8.4", "react-native-touch-id": "^4.4.1", "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#v10.9.2", diff --git a/src/status_im/keycard/card.cljs b/src/status_im/keycard/card.cljs index f3c35cef8f..707dd5b7b9 100644 --- a/src/status_im/keycard/card.cljs +++ b/src/status_im/keycard/card.cljs @@ -321,19 +321,19 @@ (defn unpair-and-delete [args] (log/debug "[keycard] unpair-and-delete") - (keycard/unpair-and-delete + (keycard/unpair card (merge args {:on-success (fn [response] (log/debug "[keycard response succ] unpair-and-delete") - (re-frame/dispatch [:keycard.callback/on-delete-success + (re-frame/dispatch [:keycard.callback/on-unpair-and-delete-success response])) :on-failure (fn [response] (log/debug "[keycard response fail] unpair-and-delete") - (re-frame/dispatch [:keycard.callback/on-delete-error + (re-frame/dispatch [:keycard.callback/on-unpair-and-delete-error (error-object->map response)]))}))) (defn import-keys [{:keys [on-success] :as args}] diff --git a/src/status_im/keycard/core.cljs b/src/status_im/keycard/core.cljs index e0b78a8980..f4a0e5f2b1 100644 --- a/src/status_im/keycard/core.cljs +++ b/src/status_im/keycard/core.cljs @@ -4,6 +4,7 @@ [status-im.keycard.common :as common] status-im.keycard.delete-key status-im.keycard.export-key + status-im.keycard.unpair [status-im.keycard.login :as login] [status-im.keycard.mnemonic :as mnemonic] [status-im.keycard.onboarding :as onboarding] @@ -192,7 +193,9 @@ ;; now for simplicity do not hide bottom sheet when generating key ;; and exporting key but should be refactored. (when-not (contains? #{:keycard/generate-and-load-key - :wallet.accounts/generate-new-keycard-account} on-verified) + :wallet.accounts/generate-new-keycard-account + :keycard/remove-key-with-unpair + :keycard/unpair-and-delete} on-verified) (common/hide-connection-sheet)) (when-not (contains? #{:keycard/unpair :keycard/generate-and-load-key diff --git a/src/status_im/keycard/delete_key.cljs b/src/status_im/keycard/delete_key.cljs index 0870dcb26c..547c3277a1 100644 --- a/src/status_im/keycard/delete_key.cljs +++ b/src/status_im/keycard/delete_key.cljs @@ -1,43 +1,8 @@ (ns status-im.keycard.delete-key - (:require [status-im.multiaccounts.logout.core :as multiaccounts.logout] - [status-im.i18n.i18n :as i18n] - [status-im.navigation :as navigation] + (:require [status-im.navigation :as navigation] [status-im.utils.fx :as fx] - [taoensso.timbre :as log] [status-im.keycard.common :as common])) -(fx/defn on-delete-success - {:events [:keycard.callback/on-delete-success]} - [{:keys [db] :as cofx}] - (let [key-uid (get-in db [:multiaccount :key-uid])] - (fx/merge cofx - {:db (-> db - (update :multiaccounts/multiaccounts dissoc key-uid) - (assoc-in [:keycard :secrets] nil) - (assoc-in [:keycard :application-info] nil) - (assoc-in [:keycard :pin] {:status nil - :error-label nil - :on-verified nil})) - ;;FIXME delete multiaccount - :utils/show-popup {:title "" - :content (i18n/label :t/card-reseted)}} - (common/clear-on-card-connected) - (multiaccounts.logout/logout)))) - -(fx/defn on-delete-error - {:events [:keycard.callback/on-delete-error]} - [{:keys [db] :as cofx} error] - (log/debug "[keycard] delete error" error) - (fx/merge cofx - {:db (assoc-in db [:keycard :pin] {:status nil - :error-label nil - :on-verified nil}) - :keycard/get-application-info nil - :utils/show-popup {:title "" - :content (i18n/label :t/something-went-wrong)}} - (common/clear-on-card-connected) - (navigation/navigate-to-cofx :keycard-settings nil))) - (fx/defn reset-card-pressed {:events [:keycard-settings.ui/reset-card-pressed]} [cofx] @@ -61,11 +26,11 @@ {:events [:keycard-settings.ui/reset-card-next-button-pressed]} [{:keys [db]}] {:db (assoc-in db [:keycard :reset-card :disabled?] true) - :dispatch [:keycard/proceed-to-reset-card]}) + :dispatch [:keycard/proceed-to-reset-card false]}) (fx/defn proceed-to-reset-card {:events [:keycard/proceed-to-reset-card]} - [{:keys [db] :as cofx}] + [{:keys [db] :as cofx} keep-keys-on-keycard?] (let [pin-retry-counter (get-in db [:keycard :application-info :pin-retry-counter]) enter-step (if (zero? pin-retry-counter) :puk :current)] (fx/merge cofx @@ -74,6 +39,8 @@ :puk [] :status nil :error-label nil - :on-verified :keycard/remove-key-with-unpair})} + :on-verified (if keep-keys-on-keycard? + :keycard/unpair-and-delete + :keycard/remove-key-with-unpair)})} (common/set-on-card-connected :keycard/navigate-to-enter-pin-screen) (common/navigate-to-enter-pin-screen)))) diff --git a/src/status_im/keycard/unpair.cljs b/src/status_im/keycard/unpair.cljs index df430808d2..7077d1aa9b 100644 --- a/src/status_im/keycard/unpair.cljs +++ b/src/status_im/keycard/unpair.cljs @@ -1,12 +1,14 @@ (ns status-im.keycard.unpair (:require [re-frame.core :as re-frame] [status-im.multiaccounts.update.core :as multiaccounts.update] - [status-im.multiaccounts.logout.core :as multiaccounts.logout] [status-im.i18n.i18n :as i18n] [status-im.navigation :as navigation] [status-im.utils.fx :as fx] [taoensso.timbre :as log] - [status-im.keycard.common :as common])) + [status-im.keycard.common :as common] + [status-im.native-module.core :as native-module] + [status-im.utils.types :as types] + [clojure.string :as string])) (fx/defn unpair-card-pressed {:events [:keycard-settings.ui/unpair-card-pressed]} @@ -42,11 +44,17 @@ (fx/defn unpair-and-delete {:events [:keycard/unpair-and-delete]} - [{:keys [db]}] - (let [pin (common/vector->string (get-in db [:keycard :pin :current])) - pairing (common/get-pairing db)] - {:keycard/unpair-and-delete {:pin pin - :pairing pairing}})) + [cofx] + (common/show-connection-sheet + cofx + {:on-card-connected :keycard/unpair-and-delete + :handler + (fn [{:keys [db]}] + (let [pin (common/vector->string (get-in db [:keycard :pin :current])) + pairing (common/get-pairing db)] + {:keycard/unpair-and-delete + {:pin pin + :pairing pairing}}))})) (fx/defn remove-pairing-from-multiaccount [cofx {:keys [remove-instance-uid?]}] @@ -106,9 +114,7 @@ {:pin pin :pairing pairing}}))})) -(fx/defn on-remove-key-success - {:events [:keycard.callback/on-remove-key-success]} - [{:keys [db] :as cofx}] +(defn handle-account-removal [{:keys [db] :as cofx} keys-removed-from-card?] (let [key-uid (get-in db [:multiaccount :key-uid]) instance-uid (get-in db [:keycard :application-info :instance-uid]) pairings (get-in db [:keycard :pairings])] @@ -117,6 +123,7 @@ (update :multiaccounts/multiaccounts dissoc key-uid) (assoc-in [:keycard :secrets] nil) (update-in [:keycard :pairings] dissoc (keyword instance-uid)) + (update-in [:keycard :pairings] dissoc instance-uid) (assoc-in [:keycard :whisper-public-key] nil) (assoc-in [:keycard :wallet-address] nil) (assoc-in [:keycard :application-info] nil) @@ -124,11 +131,23 @@ :error-label nil :on-verified nil})) :keycard/persist-pairings (dissoc pairings (keyword instance-uid)) - ;;FIXME delete multiaccount - :utils/show-popup {:title "" - :content (i18n/label :t/card-reseted)}} + :utils/show-popup {:title (i18n/label (if keys-removed-from-card? :t/profile-deleted-title :t/database-reset-title)) + :content (i18n/label (if keys-removed-from-card? :t/profile-deleted-keycard :t/database-reset-content)) + :on-dismiss #(re-frame/dispatch [:logout])}} (common/clear-on-card-connected) - (multiaccounts.logout/logout)))) + (common/hide-connection-sheet) + (native-module/delete-multiaccount + key-uid + (fn [result] + (let [{:keys [error]} (types/json->clj result)] + (if-not (string/blank? error) + (log/warn "[keycard] remove account: " error) + (log/debug "[keycard] remove account ok")))))))) + +(fx/defn on-remove-key-success + {:events [:keycard.callback/on-remove-key-success]} + [cofx] + (handle-account-removal cofx true)) (fx/defn on-remove-key-error {:events [:keycard.callback/on-remove-key-error]} @@ -141,3 +160,20 @@ {:db (assoc-in db [:keycard :pin :status] nil)} (common/set-on-card-connected :keycard/remove-key-with-unpair)) (common/show-wrong-keycard-alert true))))) + +(fx/defn on-unpair-and-delete-success + {:events [:keycard.callback/on-unpair-and-delete-success]} + [cofx] + (handle-account-removal cofx false)) + +(fx/defn on-unpair-and-delete-error + {:events [:keycard.callback/on-unpair-and-delete-error]} + [{:keys [db] :as cofx} error] + (log/debug "[keycard] unpair and delete error" error) + (let [tag-was-lost? (common/tag-lost? (:error error))] + (fx/merge cofx + (if tag-was-lost? + (fx/merge cofx + {:db (assoc-in db [:keycard :pin :status] nil)} + (common/set-on-card-connected :keycard/unpair-and-delete)) + (common/show-wrong-keycard-alert true))))) diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index c00d604d35..9dfcfa8a15 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -204,6 +204,7 @@ ;; delete profile (reg-root-key-sub :delete-profile/error :delete-profile/error) +(reg-root-key-sub :delete-profile/keep-keys-on-keycard? :delete-profile/keep-keys-on-keycard?) ;; push notifications (reg-root-key-sub :push-notifications/servers :push-notifications/servers) diff --git a/src/status_im/ui/screens/privacy_and_security_settings/delete_profile.cljs b/src/status_im/ui/screens/privacy_and_security_settings/delete_profile.cljs index 4b2575b683..47387bf051 100644 --- a/src/status_im/ui/screens/privacy_and_security_settings/delete_profile.cljs +++ b/src/status_im/ui/screens/privacy_and_security_settings/delete_profile.cljs @@ -8,32 +8,30 @@ [status-im.i18n.i18n :as i18n] [reagent.core :as reagent] [status-im.utils.security :as security] - [status-im.ui.screens.privacy-and-security-settings.events :as delete-profile])) + [status-im.ui.screens.privacy-and-security-settings.events :as delete-profile] + status-im.keycard.delete-key)) (defn valid-password? [password] (>= (count password) 6)) -(defn keycard-pin [] - #_(let [pin @(re-frame/subscribe [:keycard/pin]) - step @(re-frame/subscribe [:keycard/pin-enter-step]) - status @(re-frame/subscribe [:keycard/pin-status]) - pin-retry-counter @(re-frame/subscribe [:keycard/pin-retry-counter]) - puk-retry-counter @(re-frame/subscribe [:keycard/puk-retry-counter]) - error-label @(re-frame/subscribe [:keycard/pin-error-label])] - [pin.views/pin-view - {:pin pin - :status status - :retry-counter pin-retry-counter - :error-label error-label - :step :current}])) +(defn on-delete-profile [password] + #(do + (re-frame/dispatch + [::delete-profile/delete-profile @password]) + (reset! password nil))) + +(defn on-delete-keycard-profile [keep-keys-on-keycard?] + #(re-frame/dispatch + [:keycard/proceed-to-reset-card keep-keys-on-keycard?])) (defn delete-profile [] (let [password (reagent/atom nil) text-input-ref (atom nil)] (fn [] - (let [keycard? @(re-frame/subscribe [:keycard-multiaccount?]) - multiaccount @(re-frame/subscribe [:multiaccount]) - error @(re-frame/subscribe [:delete-profile/error])] + (let [keycard? @(re-frame/subscribe [:keycard-multiaccount?]) + multiaccount @(re-frame/subscribe [:multiaccount]) + error @(re-frame/subscribe [:delete-profile/error]) + keep-keys-on-keycard? @(re-frame/subscribe [:delete-profile/keep-keys-on-keycard?])] (when (and @text-input-ref error (not @password)) (.clear ^js @text-input-ref)) [react/view {:flex 1} @@ -50,12 +48,31 @@ {:title (multiaccounts/displayed-name multiaccount) :icon [chat-icon.screen/contact-icon-contacts-tab (multiaccounts/displayed-photo multiaccount)]}] - [quo/text {:style {:margin-horizontal 24} - :align :center - :color :negative} - (i18n/label :t/delete-profile-warning)] - (if keycard? - [keycard-pin] + (when keycard? + [react/view + [quo/list-header (i18n/label :t/actions)] + [quo/list-item {:title (i18n/label :t/delete-keys-keycard) + :accessory :checkbox + :active (not keep-keys-on-keycard?) + :on-press #(re-frame/dispatch [::delete-profile/keep-keys-on-keycard (not keep-keys-on-keycard?)])}] + [quo/list-item {:title (i18n/label :t/unpair-keycard) + :subtitle (i18n/label :t/unpair-keycard-warning) + :subtitle-max-lines 4 + :disabled true + :active true + :accessory :checkbox}] + [quo/list-item {:title (i18n/label :t/reset-database) + :subtitle (i18n/label :t/reset-database-warning-keycard) + :subtitle-max-lines 4 + :disabled true + :active true + :accessory :checkbox}]]) + (when-not keycard? + [quo/text {:style {:margin-horizontal 24} + :align :center + :color :negative} + (i18n/label :t/delete-profile-warning)]) + (when-not keycard? [quo/text-input {:style {:margin-horizontal 36 :margin-top 36} @@ -71,16 +88,18 @@ (if (= :wrong-password error) (i18n/label :t/wrong-password) (str error)))}])] - (when-not keycard? - [react/view {:style {:align-items :center}} - [quo/separator] - [react/view - {:style {:margin-vertical 8}} - [quo/button {:on-press #(do - (re-frame/dispatch - [::delete-profile/delete-profile @password]) - (reset! password nil)) - :theme :negative - :accessibility-label :delete-profile-confirm - :disabled ((complement valid-password?) @password)} - (i18n/label :t/delete-profile)]]])]])))) + [react/view {:style {:align-items :center}} + (when-not keycard? + [quo/separator]) + (when (and keycard? (not keep-keys-on-keycard?)) + [quo/text {:style {:margin-horizontal 24 :margin-bottom 16} + :align :center + :color :negative} + (i18n/label :t/delete-profile-warning)]) + [react/view + {:style {:margin-vertical 8}} + [quo/button {:on-press (if keycard? (on-delete-keycard-profile keep-keys-on-keycard?) (on-delete-profile password)) + :theme :negative + :accessibility-label :delete-profile-confirm + :disabled (and (not keycard?) ((complement valid-password?) @password))} + (i18n/label :t/delete-profile)]]]]])))) diff --git a/src/status_im/ui/screens/privacy_and_security_settings/events.cljs b/src/status_im/ui/screens/privacy_and_security_settings/events.cljs index 6f2e8fbf98..0284c27e4b 100644 --- a/src/status_im/ui/screens/privacy_and_security_settings/events.cljs +++ b/src/status_im/ui/screens/privacy_and_security_settings/events.cljs @@ -65,3 +65,8 @@ [{:keys [db]} error] (log/info "[delete-profile] on-failure" error) {:db (assoc db :delete-profile/error error)}) + +(fx/defn keep-keys-on-keycard + {:events [::keep-keys-on-keycard]} + [{:keys [db] :as cofx} checked?] + {:db (assoc-in db [:delete-profile/keep-keys-on-keycard?] checked?)}) \ No newline at end of file diff --git a/src/status_im/ui/screens/privacy_and_security_settings/views.cljs b/src/status_im/ui/screens/privacy_and_security_settings/views.cljs index 13dd317d44..e4ca2ab8d4 100644 --- a/src/status_im/ui/screens/privacy_and_security_settings/views.cljs +++ b/src/status_im/ui/screens/privacy_and_security_settings/views.cljs @@ -16,8 +16,7 @@ (views/defview privacy-and-security [] (views/letsubs [{:keys [mnemonic preview-privacy? webview-allow-permission-requests?]} [:multiaccount] supported-biometric-auth [:supported-biometric-auth] - auth-method [:auth-method] - keycard? [:keycard-multiaccount?]] + auth-method [:auth-method]] [react/view {:flex 1 :background-color colors/white} [topbar/topbar {:title (i18n/label :t/privacy-and-security)}] [react/scroll-view {:padding-vertical 8} @@ -78,14 +77,11 @@ :on-press #(re-frame/dispatch [:multiaccounts.ui/webview-permission-requests-switched ((complement boolean) webview-allow-permission-requests?)])}]) - ;; TODO(rasom): remove this condition when kk support will be added - (when-not keycard? - [separator]) - (when-not keycard? - [quo/list-item - {:size :small - :theme :negative - :title (i18n/label :t/delete-my-profile) - :on-press #(re-frame/dispatch [:navigate-to :delete-profile]) - :accessibility-label :dapps-permissions-button - :chevron true}])]])) + [separator] + [quo/list-item + {:size :small + :theme :negative + :title (i18n/label :t/delete-my-profile) + :on-press #(re-frame/dispatch [:navigate-to :delete-profile]) + :accessibility-label :dapps-permissions-button + :chevron true}]]])) diff --git a/translations/en.json b/translations/en.json index ce2bf717d6..37cb328097 100644 --- a/translations/en.json +++ b/translations/en.json @@ -396,6 +396,7 @@ "delete-profile-warning": "Warning: If you don’t have your seed phrase written down, you will lose access to your funds after you delete your profile", "profile-deleted-title": "Profile deleted", "profile-deleted-content": "Your profile was successfully deleted", + "profile-deleted-keycard": "You can now restore another keypair on your Keycard", "deny": "Deny", "description": "Description", "dev-mode": "Development mode", @@ -1219,6 +1220,8 @@ "unpair-card-confirmation": "This operation will unpair card from current device. Requires 6-digit passcode authorization. Do you want to proceed?", "unpaired-keycard-text": "The Keycard you tapped is not associated with this phone", "unpaired-keycard-title": "Looks like your card has been unpaired", + "unpair-keycard": "Unpair Keycard from this phone", + "unpair-keycard-warning": "Your pairing code/PUK & PIN remain unchanged", "update": "Update", "url": "URL", "usd-currency": "USD", @@ -1313,6 +1316,7 @@ "keycard-free-pairing-slots": "Keycard has {{n}} free pairing slots", "public-chat-description": "Join public chats for your interests! Anyone can start a new one.", "delete-account": "Delete account", + "delete-keys-keycard": "Delete keys from Keycard", "watch-only": "Watch-only", "cant-report-bug": "Can't report a bug", "mail-should-be-configured": "Mail client should be configured", @@ -1434,6 +1438,8 @@ "transfers-fetching-failure": "Transfers history could not be updated. Check your connection and pull down to try again", "move-and-reset": "Move and Reset", "move-keystore-file-to-keycard": "Move keystore file to keycard?", + "database-reset-title": "Database reset", + "database-reset-content": "Chats, contacts and settings have been deleted. You can use your account with your Keycard", "database-reset-warning": "Database will be reset. Chats, contacts and settings will be deleted", "empty-keycard-required": "Requires an empty Keycard", "current": "Current", @@ -1446,6 +1452,7 @@ "select-new-location-for-keys": "Select a new location to save your private key(s)", "reset-database": "Reset database", "reset-database-warning": "Delete chats, contacts and settings. Required when you’ve lost your password", + "reset-database-warning-keycard": "Delete chats, contacts and settings.", "key-managment": "Key management", "choose-actions": "Choose actions", "master-account": "Master account", diff --git a/yarn.lock b/yarn.lock index a97db8afb0..9d3e3a37e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6751,9 +6751,9 @@ react-native-splash-screen@^3.2.0: resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45" integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg== -"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.31": - version "2.5.31" - resolved "git+https://github.com/status-im/react-native-status-keycard.git#67ba4d5596ae3f7fd123c0f1c925e98e8def493f" +"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.32": + version "2.5.32" + resolved "git+https://github.com/status-im/react-native-status-keycard.git#f602fadf800937fc1de92aa18c2e58c372eb1bed" react-native-svg@^9.8.4: version "9.13.6"