[#19917] feat: rename keypair from wallet settings (#19939)

This commit is contained in:
Mohsen 2024-05-13 17:07:33 +03:00 committed by GitHub
parent 006824e0ed
commit 6be1adb40e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 239 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

View File

@ -0,0 +1,23 @@
(ns status-im.common.validation.keypair
(:require [clojure.string :as string]
[status-im.common.validation.general :as validators]
[status-im.constants :as constants]
utils.emojilib
[utils.i18n :as i18n]))
(defn keypair-too-short?
[s]
(< (-> s str string/trim count) constants/key-pair-name-min-length))
(defn keypair-too-long?
[s]
(> (-> s str string/trim count) constants/key-pair-name-max-length))
(defn validation-keypair-name
[s]
(cond
(string/blank? s) nil
(validators/has-emojis? s) (i18n/label :t/key-name-error-emoji)
(validators/has-special-characters? s) (i18n/label :t/key-name-error-special-char)
(keypair-too-short? s) (i18n/label :t/your-key-pair-name-is-too-short)
(keypair-too-long? s) (i18n/label :t/your-key-pair-name-is-too-long)))

View File

@ -0,0 +1,27 @@
(ns status-im.common.validation.keypair-test
(:require
[cljs.test :refer-macros [deftest are]]
[status-im.common.validation.keypair :as keypair-validator]
[utils.i18n :as i18n]))
(deftest keypair-name-too-short-test
(are [arg expected]
(expected (keypair-validator/keypair-too-short? arg))
"abc" true?
"abcdef" false?))
(deftest keypair-name-too-long-test
(are [arg expected]
(expected (keypair-validator/keypair-too-long? arg))
(apply str (repeat 25 "a")) true?
"abcdef" false?))
(deftest validation-keypair-name-test
(are [arg expected]
(= (keypair-validator/validation-keypair-name arg) expected)
nil nil
"" nil
"name !" (i18n/label :t/key-name-error-special-char)
"Hello 😊" (i18n/label :t/key-name-error-emoji)
"abc" (i18n/label :t/your-key-pair-name-is-too-short)
(apply str (repeat 25 "a")) (i18n/label :t/your-key-pair-name-is-too-long)))

View File

@ -77,6 +77,9 @@
(def ^:const contact-request-message-state-declined 3)
(def ^:const contact-request-message-max-length 280)
(def ^:const key-pair-name-max-length 20)
(def ^:const key-pair-name-min-length 5)
(def request-to-join-pending-state 1)
(def reactions

View File

@ -0,0 +1,32 @@
(ns status-im.contexts.settings.wallet.events
(:require
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(rf/reg-event-fx
:wallet/rename-keypair-success
(fn [{:keys [db]} [key-uid name]]
{:db (update-in db
[:wallet :keypairs]
(fn [keypairs]
(map (fn [keypair]
(if (= (keypair :key-uid) key-uid)
(assoc keypair :name name)
keypair))
keypairs)))
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
{:type :positive
:text (i18n/label :t/key-pair-name-updated)}]]]}))
(defn rename-keypair
[_ [{:keys [key-uid keypair-name]}]]
{:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [key-uid keypair-name]
:on-success [:wallet/rename-keypair-success key-uid keypair-name]
:on-error #(log/info "failed to rename keypair " %)}]]]})
(rf/reg-event-fx :wallet/rename-keypair rename-keypair)

View File

@ -0,0 +1,20 @@
(ns status-im.contexts.settings.wallet.events-test
(:require
[cljs.test :refer-macros [deftest is]]
matcher-combinators.test
[status-im.contexts.settings.wallet.events :as sut]))
(def key-uid "0xfef454bb492ee4677594f8e05921c84f336fa811deb99b8d922477cc87a38b98")
(deftest rename-keypair-test
(let [new-keypair-name "key pair new"
cofx {:db {}}
expected {:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [key-uid new-keypair-name]
:on-success [:wallet/rename-keypair-success key-uid new-keypair-name]
:on-error fn?}]]]}]
(is (match? expected
(sut/rename-keypair cofx
[{:key-uid key-uid
:keypair-name new-keypair-name}])))))

View File

@ -1,6 +1,19 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.actions.view
(:require [quo.core :as quo]))
(:require [quo.core :as quo]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn on-rename-request
[data]
(rf/dispatch [:open-modal :screen/settings.rename-keypair data]))
(defn view
[props]
[quo/drawer-top props])
[props data]
[:<>
[quo/drawer-top props]
[quo/action-drawer
[(when (= (:type props) :keypair)
[{:icon :i/edit
:accessibility-label :rename-key-pair
:label (i18n/label :t/rename-key-pair)
:on-press #(on-rename-request data)}])]]])

View File

@ -0,0 +1,11 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.rename.style)
(def header-container
{:margin-bottom 8})
(def bottom-action
{:margin-horizontal -20})
(def error-container
{:margin-left 20
:margin-vertical 8})

View File

@ -0,0 +1,84 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.rename.view
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.validation.keypair :as keypair-validator]
[status-im.constants :as constants]
[status-im.contexts.settings.wallet.keypairs-and-accounts.rename.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn navigate-back [] (rf/dispatch [:navigate-back]))
(defn view
[]
(let [{:keys [name key-uid]} (rf/sub [:get-screen-params])
customization-color (rf/sub [:profile/customization-color])
[unsaved-keypair-name set-unsaved-keypair-name] (rn/use-state name)
[error-msg set-error-msg] (rn/use-state nil)
[typing? set-typing?] (rn/use-state false)
validate-keypair-name (rn/use-callback
(debounce/debounce
(fn [name]
(set-error-msg
(keypair-validator/validation-keypair-name
name))
(set-typing? false))
300))
on-change-text (rn/use-callback (fn [text]
(set-typing? true)
(set-unsaved-keypair-name
text)
(validate-keypair-name text)))
on-clear (rn/use-callback (fn []
(on-change-text "")))
on-save (rn/use-callback #(rf/dispatch
[:wallet/rename-keypair
{:key-uid key-uid
:keypair-name
unsaved-keypair-name}])
[unsaved-keypair-name key-uid])]
[floating-button-page/view
{:header [quo/page-nav
{:icon-name :i/close
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save)
:button-one-props {:disabled? (or typing?
(string/blank? unsaved-keypair-name)
(not (string/blank? error-msg)))
:customization-color customization-color
:on-press on-save}
:container-style style/bottom-action}]}
[quo/page-top
{:container-style style/header-container
:title (i18n/label :t/rename-key-pair)
:description :context-tag
:context-tag {:type :icon
:size 24
:context name
:icon :i/seed-phrase}}]
[quo/input
{:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:default-value unsaved-keypair-name
:char-limit constants/key-pair-name-max-length
:max-length constants/key-pair-name-max-length
:auto-focus true
:clearable? (not (string/blank? unsaved-keypair-name))
:on-clear on-clear
:on-change-text on-change-text
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]))

View File

@ -15,14 +15,15 @@
(defn on-options-press
[{:keys [theme]
:as props}]
:as props} keypair]
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/view props])
{:content (fn [] [actions/view props keypair])
:theme theme}]))
(defn- keypair
[{keypair-type :type
:keys [accounts name]}
:keys [accounts name]
:as item}
_ _
{:keys [profile-picture compressed-key customization-color]}]
(let [theme (quo.theme/use-theme)
@ -42,7 +43,8 @@
:profile-picture profile-picture)
(not default-keypair?)
(assoc :type :keypair
:icon-avatar :i/seed))))
:icon-avatar :i/seed))
item))
[customization-color default-keypair? name
profile-picture shortened-key theme])]
[quo/keypair

View File

@ -6,16 +6,14 @@
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.validation.general :as validators]
[status-im.constants :as constants]
[status-im.contexts.wallet.add-account.create-account.key-pair-name.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def ^:private key-pair-name-max-length 15)
(def ^:private key-pair-name-min-length 5)
(def error-messages
{:too-long (i18n/label :t/key-name-error-length)
:too-short (i18n/label :t/key-name-error-too-short {:count key-pair-name-min-length})
:too-short (i18n/label :t/key-name-error-too-short {:count constants/key-pair-name-min-length})
:emoji (i18n/label :t/key-name-error-emoji)
:special-char (i18n/label :t/key-name-error-special-char)})
@ -33,10 +31,10 @@
(fn [value]
(set-key-pair-name value)
(cond
(> (count value) key-pair-name-max-length)
(> (count value) constants/key-pair-name-max-length)
(set-error :too-long)
(< 0 (count value) key-pair-name-min-length)
(< 0 (count value) constants/key-pair-name-min-length)
(set-error :too-short)
(validators/has-emojis? value)
@ -81,7 +79,7 @@
{:container-style style/input
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:char-limit key-pair-name-max-length
:char-limit constants/key-pair-name-max-length
:auto-focus true
:on-change-text on-change-text
:error error}]

View File

@ -4,6 +4,7 @@
[clojure.string :as string]
[react-native.platform :as platform]
[status-im.constants :as constants]
[status-im.contexts.settings.wallet.events]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.db :as db]

View File

@ -57,6 +57,7 @@
[status-im.contexts.profile.settings.screens.password.change-password.view :as change-password]
[status-im.contexts.profile.settings.screens.password.view :as settings-password]
[status-im.contexts.profile.settings.view :as settings]
[status-im.contexts.settings.wallet.keypairs-and-accounts.rename.view :as keypair-rename]
[status-im.contexts.settings.wallet.keypairs-and-accounts.view :as keypairs-and-accounts]
[status-im.contexts.settings.wallet.saved-addresses.view :as saved-addresses-settings]
[status-im.contexts.settings.wallet.wallet-options.view :as wallet-options]
@ -503,6 +504,10 @@
:options options/transparent-modal-screen-options
:component wallet-options/view}
{:name :screen/settings.rename-keypair
:options (assoc options/dark-screen :sheet? true)
:component keypair-rename/view}
{:name :screen/settings.saved-addresses
:options options/transparent-modal-screen-options
:component saved-addresses-settings/view}

View File

@ -183,9 +183,10 @@
:<- [:wallet/keypairs]
(fn [keypairs [_ format-options]]
(->> keypairs
(map (fn [{:keys [accounts name type]}]
(map (fn [{:keys [accounts name type key-uid]}]
{:type (keyword type)
:name name
:key-uid key-uid
:accounts (format-settings-keypair-accounts accounts format-options)})))))
(rf/reg-sub

View File

@ -1255,6 +1255,7 @@
"remove-network": "Remove network",
"remove-token": "Remove token",
"removed": "removed",
"rename-key-pair": "Rename key pair",
"repeat-pin": "Repeat new 6-digit passcode",
"repeat-puk": "Repeat new 12-digit PUK",
"report-bug-email-template": "1. Issue Description\n{{description}}\n\n\n2. Steps to reproduce\n{{steps}}\n\n\n3. Attach screenshots that can demo the problem, please\n",
@ -2570,6 +2571,7 @@
"keypair-name": "Key pair name",
"keypair-name-description": "Name key pair for your own personal reference",
"keypair-name-input-placeholder": "Collectibles account, Old vault....",
"key-pair-name-updated": "Key pair name updated",
"goerli-testnet-toggle-confirmation": "Are you sure you want to toggle Goerli? This will log you out and you will have to login again.",
"bridged-to": "Bridged to {{network}}",
"slide-to-bridge": "Slide to bridge",
@ -2590,6 +2592,8 @@
"other": "{{count}} addresses"
},
"max": "Max: {{number}}",
"your-key-pair-name-is-too-long": "Your key pair name is too long",
"your-key-pair-name-is-too-short": "Your key pair name is too short",
"key-name-error-length": "Key name too long",
"key-name-error-emoji": "Emojis are not allowed",
"key-name-error-special-char": "Special characters are not allowed",