Skip to content

Commit e2b9e12

Browse files
authored
feat: Keypair name handling (#19423)
feat: Keypair name handling (#19423)
1 parent a03cc3c commit e2b9e12

File tree

15 files changed

+142
-91
lines changed

15 files changed

+142
-91
lines changed

src/quo/components/info/info_message.cljs

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
:text-color colors/white ;; text color override
2424
:icon-color colors/white ;; icon color override
2525
:no-icon-color? false ;; disable tint color for icon"
26-
[{:keys [type size theme icon text-color icon-color no-icon-color? style accessibility-label]} message]
26+
[{:keys [type size theme icon text-color icon-color no-icon-color? style accessibility-label
27+
container-style]} message]
2728
(let [weight (if (= size :default) :regular :medium)
2829
icon-size (if (= size :default) 16 12)
2930
size (if (= size :default) :paragraph-2 :label)
@@ -32,7 +33,8 @@
3233
[rn/view
3334
{:style (merge {:flex-direction :row
3435
:align-items :center}
35-
style)}
36+
style
37+
container-style)}
3638
[quo.icons/icon icon
3739
{:color icon-color
3840
:no-color no-icon-color?

src/quo/components/inputs/input/style.cljs

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@
134134
:align-items :flex-end})
135135

136136
(defn counter-color
137-
[current-chars char-limit variant-colors]
137+
[{:keys [current-chars char-limit variant-colors theme]}]
138138
{:color (if (> current-chars char-limit)
139-
colors/danger-60
139+
(colors/resolve-color :danger theme)
140140
(:label variant-colors))})
141141

142142
(defn button

src/quo/components/inputs/input/view.cljs

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[react-native.platform :as platform]))
99

1010
(defn- label-&-counter
11-
[{:keys [label current-chars char-limit variant-colors]}]
11+
[{:keys [label current-chars char-limit variant-colors theme]}]
1212
[rn/view
1313
{:accessibility-label :input-labels
1414
:style style/texts-container}
@@ -22,7 +22,10 @@
2222
(str current-chars "/"))]
2323
[rn/view {:style style/counter-container}
2424
[text/text
25-
{:style (style/counter-color current-chars char-limit variant-colors)
25+
{:style (style/counter-color {:current-chars current-chars
26+
:char-limit char-limit
27+
:variant-colors variant-colors
28+
:theme theme})
2629
:weight :regular
2730
:size :paragraph-2}
2831
count-text]])])
@@ -114,7 +117,8 @@
114117
{:variant-colors variant-colors
115118
:label label
116119
:current-chars char-count
117-
:char-limit char-limit}])
120+
:char-limit char-limit
121+
:theme theme}])
118122
[rn/view {:style (style/input-container colors-by-status small? disabled?)}
119123
(when-let [{:keys [icon-name]} left-icon]
120124
[left-accessory

src/status_im/common/router.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[legacy.status-im.ethereum.ens :as ens]
66
[native-module.core :as native-module]
77
[re-frame.core :as re-frame]
8-
[status-im.common.validators :as validators]
8+
[status-im.common.validation.general :as validators]
99
[status-im.constants :as constants]
1010
[status-im.contexts.chat.events :as chat.events]
1111
[taoensso.timbre :as log]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
(ns status-im.common.validation.general
2+
(:require
3+
[status-im.constants :as constants]
4+
[utils.emojilib :as emoji]))
5+
6+
(defn valid-public-key?
7+
[s]
8+
(and (string? s)
9+
(not-empty s)
10+
(boolean (re-matches constants/regx-public-key s))))
11+
12+
(defn valid-compressed-key?
13+
[s]
14+
(and (string? s)
15+
(not-empty s)
16+
(boolean (re-matches constants/regx-compressed-key s))))
17+
18+
(defn has-emojis? [s] (boolean (re-find emoji/emoji-regex s)))
19+
20+
(def no-special-chars-regex #"^[a-zA-Z0-9\-_ ]+$")
21+
(defn has-special-characters?
22+
[s]
23+
(and (not (= s ""))
24+
(not (re-find no-special-chars-regex s))))
25+

src/status_im/common/validators_test.cljs src/status_im/common/validation/general_test.cljs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
(ns status-im.common.validators-test
1+
(ns status-im.common.validation.general-test
22
(:require
33
[cljs.test :refer-macros [deftest testing is]]
4-
[status-im.common.validators :refer [valid-compressed-key?]]))
4+
[status-im.common.validation.general :refer [valid-compressed-key?]]))
55

66
(deftest test-valid-compressed-key
77
(testing "valid"
@@ -32,3 +32,4 @@
3232
(testing "contains l"
3333
(is (not (valid-compressed-key?
3434
"zQ3shWj4WaBdf2zYKCkXe6PHxDxNTzZyid1i75879Ue9cX9gl")))))
35+
+27-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(ns status-im.common.validation.profile
22
(:require [clojure.string :as string]
3+
[status-im.common.validation.general :as validators]
34
[status-im.constants :as constants]
45
utils.emojilib
56
[utils.i18n :as i18n]))
@@ -8,16 +9,10 @@
89
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
910
(def min-length 5)
1011

11-
(def status-regex #"^[a-zA-Z0-9\-_ ]+$")
12-
1312
(def common-names ["Ethereum" "Bitcoin"])
1413

15-
(defn has-emojis? [s] (boolean (re-find utils.emojilib/emoji-regex s)))
16-
1714
(defn has-common-names? [s] (pos? (count (filter #(string/includes? s %) common-names))))
1815

19-
(defn has-special-characters? [s] (not (re-find status-regex s)))
20-
2116
(defn name-too-short? [s] (< (count (string/trim (str s))) min-length))
2217

2318
(defn name-too-long? [s] (> (count (string/trim (str s))) constants/profile-name-max-length))
@@ -27,33 +22,37 @@
2722
(defn validation-name
2823
[s]
2924
(cond
30-
(string/blank? s) nil
31-
(string/ends-with? s "-eth") (i18n/label :t/ending-not-allowed {:ending "-eth"})
32-
(string/ends-with? s "_eth") (i18n/label :t/ending-not-allowed {:ending "_eth"})
33-
(string/ends-with? s ".eth") (i18n/label :t/ending-not-allowed {:ending ".eth"})
34-
(string/starts-with? s " ") (i18n/label :t/start-with-space)
35-
(string/ends-with? s " ") (i18n/label :t/ends-with-space)
36-
(has-common-names? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/common-names)})
37-
(has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)})
38-
(has-special-characters? s) (i18n/label :t/are-not-allowed
39-
{:check (i18n/label :t/special-characters)})
40-
(name-too-short? s) (i18n/label :t/minimum-characters {:min-chars min-length})
41-
(name-too-long? s) (i18n/label :t/profile-name-is-too-long)))
25+
(string/blank? s) nil
26+
(string/ends-with? s "-eth") (i18n/label :t/ending-not-allowed {:ending "-eth"})
27+
(string/ends-with? s "_eth") (i18n/label :t/ending-not-allowed {:ending "_eth"})
28+
(string/ends-with? s ".eth") (i18n/label :t/ending-not-allowed {:ending ".eth"})
29+
(string/starts-with? s " ") (i18n/label :t/start-with-space)
30+
(string/ends-with? s " ") (i18n/label :t/ends-with-space)
31+
(has-common-names? s) (i18n/label :t/are-not-allowed
32+
{:check (i18n/label :t/common-names)})
33+
(validators/has-emojis? s) (i18n/label :t/are-not-allowed
34+
{:check (i18n/label :t/emojis)})
35+
(validators/has-special-characters? s) (i18n/label :t/are-not-allowed
36+
{:check (i18n/label :t/special-characters)})
37+
(name-too-short? s) (i18n/label :t/minimum-characters {:min-chars min-length})
38+
(name-too-long? s) (i18n/label :t/profile-name-is-too-long)))
4239

4340
(defn validation-bio
4441
[s]
4542
(cond
46-
(string/blank? s) nil
47-
(has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)})
48-
(has-special-characters? s) (i18n/label :t/are-not-allowed
49-
{:check (i18n/label :t/special-characters)})
50-
(bio-too-long? s) (i18n/label :t/bio-is-too-long)))
43+
(string/blank? s) nil
44+
(validators/has-emojis? s) (i18n/label :t/are-not-allowed
45+
{:check (i18n/label :t/emojis)})
46+
(validators/has-special-characters? s) (i18n/label :t/are-not-allowed
47+
{:check (i18n/label :t/special-characters)})
48+
(bio-too-long? s) (i18n/label :t/bio-is-too-long)))
5149

5250
(defn validation-nickname
5351
[s]
5452
(cond
55-
(string/blank? s) nil
56-
(has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)})
57-
(has-special-characters? s) (i18n/label :t/are-not-allowed
58-
{:check (i18n/label :t/special-characters)})
59-
(name-too-long? s) (i18n/label :t/nickname-is-too-long)))
53+
(string/blank? s) nil
54+
(validators/has-emojis? s) (i18n/label :t/are-not-allowed
55+
{:check (i18n/label :t/emojis)})
56+
(validators/has-special-characters? s) (i18n/label :t/are-not-allowed
57+
{:check (i18n/label :t/special-characters)})
58+
(name-too-long? s) (i18n/label :t/nickname-is-too-long)))

src/status_im/common/validation/profile_test.cljs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
(ns status-im.common.validation.profile-test
22
(:require
33
[cljs.test :refer-macros [deftest are]]
4+
[status-im.common.validation.general :as validator]
45
[status-im.common.validation.profile :as profile-validator]
56
[utils.i18n :as i18n]))
67

78
(deftest has-emojis-test
89
(are [arg expected]
9-
(expected (profile-validator/has-emojis? arg))
10+
(expected (validator/has-emojis? arg))
1011
"Hello 😊" true?
1112
"Hello" false?))
1213

@@ -18,7 +19,7 @@
1819

1920
(deftest has-special-characters-test
2021
(are [arg expected]
21-
(expected (profile-validator/has-special-characters? arg))
22+
(expected (validator/has-special-characters? arg))
2223
"@name" true?
2324
"name" false?))
2425

src/status_im/common/validators.cljs

-15
This file was deleted.

src/status_im/contexts/chat/home/add_new_contact/events.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require
33
[clojure.string :as string]
44
[re-frame.core :as re-frame]
5-
[status-im.common.validators :as validators]
5+
[status-im.common.validation.general :as validators]
66
[status-im.contexts.chat.contacts.events :as data-store.contacts]
77
status-im.contexts.chat.home.add-new-contact.effects
88
[utils.ens.stateofus :as stateofus]

src/status_im/contexts/shell/qr_reader/view.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[react-native.hooks :as hooks]
66
[status-im.common.router :as router]
77
[status-im.common.scan-qr-code.view :as scan-qr-code]
8-
[status-im.common.validators :as validators]
8+
[status-im.common.validation.general :as validators]
99
[status-im.contexts.communities.events]
1010
[status-im.contexts.wallet.common.validation :as wallet-validation]
1111
[utils.debounce :as debounce]

src/status_im/contexts/wallet/create_account/edit_derivation_path/view.cljs

-1
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,3 @@
143143
:delete-key? true}])]))))
144144

145145
(def view (quo.theme/with-theme view-internal))
146-

src/status_im/contexts/wallet/create_account/new_keypair/keypair_name/style.cljs

+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@
77

88
(def bottom-action
99
{:margin-horizontal -20})
10+
11+
(def error-container
12+
{:margin-left 20
13+
:margin-vertical 8})

src/status_im/contexts/wallet/create_account/new_keypair/keypair_name/view.cljs

+60-32
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,72 @@
22
(:require
33
[quo.core :as quo]
44
[react-native.core :as rn]
5-
[reagent.core :as reagent]
65
[status-im.common.floating-button-page.view :as floating-button-page]
6+
[status-im.common.validation.general :as validators]
77
[status-im.contexts.wallet.create-account.new-keypair.keypair-name.style :as style]
88
[utils.i18n :as i18n]
99
[utils.re-frame :as rf]))
1010

1111
(def keypair-name-max-length 15)
12+
(def keypair-name-min-length 5)
13+
14+
(def error-messages
15+
{:length (i18n/label :t/key-name-error-length)
16+
:emoji (i18n/label :t/key-name-error-emoji)
17+
:special-char (i18n/label :t/key-name-error-special-char)})
18+
19+
(defn navigate-back [] (rf/dispatch [:navigate-back]))
1220

1321
(defn view
1422
[]
15-
(let [keypair-name (reagent/atom "")]
16-
(fn []
17-
(let [customization-color (rf/sub [:profile/customization-color])]
18-
[rn/view {:style {:flex 1}}
19-
[floating-button-page/view
20-
{:header [quo/page-nav
21-
{:icon-name :i/arrow-left
22-
:on-press #(rf/dispatch [:navigate-back])
23-
:accessibility-label :top-bar}]
24-
:footer [quo/bottom-actions
25-
{:actions :one-action
26-
:button-one-label (i18n/label :t/continue)
27-
:button-one-props {:disabled? (or (zero? (count @keypair-name))
28-
(> (count @keypair-name)
29-
keypair-name-max-length))
30-
:customization-color customization-color
31-
:on-press #(rf/dispatch [:wallet/new-keypair-continue
32-
{:keypair-name
33-
@keypair-name}])}
34-
:container-style style/bottom-action}]}
35-
[quo/text-combinations
36-
{:container-style style/header-container
37-
:title (i18n/label :t/keypair-name)
38-
:description (i18n/label :t/keypair-name-description)}]
39-
[quo/input
40-
{:container-style {:margin-horizontal 20}
41-
:placeholder (i18n/label :t/keypair-name-input-placeholder)
42-
:label (i18n/label :t/keypair-name)
43-
:char-limit keypair-name-max-length
44-
:auto-focus true
45-
:on-change-text #(reset! keypair-name %)}]]]))))
23+
(let [[keypair-name set-keypair-name] (rn/use-state "")
24+
customization-color (rf/sub [:profile/customization-color])
25+
[error set-error] (rn/use-state false)
26+
on-change-text (rn/use-callback (fn [value]
27+
(set-keypair-name value)
28+
(cond
29+
(> (count value) keypair-name-max-length)
30+
(set-error :length)
31+
(validators/has-emojis? value) (set-error
32+
:emoji)
33+
(validators/has-special-characters? value)
34+
(set-error :special-char)
35+
:else (set-error nil))))
36+
on-continue (rn/use-callback #(rf/dispatch [:wallet/new-keypair-continue
37+
{:keypair-name
38+
keypair-name}])
39+
[keypair-name])]
40+
[rn/view {:style {:flex 1}}
41+
[floating-button-page/view
42+
{:header [quo/page-nav
43+
{:icon-name :i/arrow-left
44+
:on-press navigate-back
45+
:accessibility-label :top-bar}]
46+
:footer [quo/bottom-actions
47+
{:actions :one-action
48+
:button-one-label (i18n/label :t/continue)
49+
:button-one-props {:disabled? (or (pos? error)
50+
(<= (count keypair-name)
51+
keypair-name-min-length))
52+
:customization-color customization-color
53+
:on-press on-continue}
54+
:container-style style/bottom-action}]}
55+
[quo/text-combinations
56+
{:container-style style/header-container
57+
:title (i18n/label :t/keypair-name)
58+
:description (i18n/label :t/keypair-name-description)}]
59+
[quo/input
60+
{:container-style {:margin-horizontal 20}
61+
:placeholder (i18n/label :t/keypair-name-input-placeholder)
62+
:label (i18n/label :t/keypair-name)
63+
:char-limit keypair-name-max-length
64+
:auto-focus true
65+
:on-change-text on-change-text
66+
:error error}]
67+
(when error
68+
[quo/info-message
69+
{:type :error
70+
:size :default
71+
:icon :i/info
72+
:container-style style/error-container}
73+
(get error-messages error)])]]))

translations/en.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -2562,5 +2562,8 @@
25622562
"one": "1 address",
25632563
"other": "{{count}} addresses"
25642564
},
2565-
"max": "Max: {{number}}"
2565+
"max": "Max: {{number}}",
2566+
"key-name-error-length": "Key name too long",
2567+
"key-name-error-emoji": "Emojis are not allowed",
2568+
"key-name-error-special-char": "Special characters are not allowed"
25662569
}

0 commit comments

Comments
 (0)