From 3145ecd6bfdfabc830916d96a3c03d67229b92fd Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 7 Mar 2024 15:23:07 +0300 Subject: [PATCH] [#19037] feat: new design for manage nickname (#19085) --- src/status_im/common/validation/profile.cljs | 13 ++- .../profile/contact/actions/view.cljs | 79 ++++++++++++------ .../profile/contact/add_nickname/style.cljs | 6 ++ .../profile/contact/add_nickname/view.cljs | 81 +++++++++++++++++++ .../contexts/profile/contact/view.cljs | 2 +- translations/en.json | 4 + 6 files changed, 156 insertions(+), 29 deletions(-) create mode 100644 src/status_im/contexts/profile/contact/add_nickname/style.cljs create mode 100644 src/status_im/contexts/profile/contact/add_nickname/view.cljs diff --git a/src/status_im/common/validation/profile.cljs b/src/status_im/common/validation/profile.cljs index 2272fd6f1e..4b3454e03f 100644 --- a/src/status_im/common/validation/profile.cljs +++ b/src/status_im/common/validation/profile.cljs @@ -29,7 +29,7 @@ (defn validation-name [s] (cond - (or (= s nil) (= s "")) nil + (string/blank? s) nil (string/ends-with? s "-eth") (i18n/label :t/ending-not-allowed {:ending "-eth"}) (string/ends-with? s "_eth") (i18n/label :t/ending-not-allowed {:ending "_eth"}) (string/ends-with? s ".eth") (i18n/label :t/ending-not-allowed {:ending ".eth"}) @@ -45,8 +45,17 @@ (defn validation-bio [s] (cond - (or (= s nil) (= s "")) nil + (string/blank? s) nil (has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)}) (has-special-characters? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/special-characters)}) (bio-too-long? s) (i18n/label :t/bio-is-too-long))) + +(defn validation-nickname + [s] + (cond + (string/blank? s) nil + (has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)}) + (has-special-characters? s) (i18n/label :t/are-not-allowed + {:check (i18n/label :t/special-characters)}) + (name-too-long? s) (i18n/label :t/nickname-is-too-long))) diff --git a/src/status_im/contexts/profile/contact/actions/view.cljs b/src/status_im/contexts/profile/contact/actions/view.cljs index 83fa22292f..081926412b 100644 --- a/src/status_im/contexts/profile/contact/actions/view.cljs +++ b/src/status_im/contexts/profile/contact/actions/view.cljs @@ -1,31 +1,58 @@ (ns status-im.contexts.profile.contact.actions.view - (:require [quo.core :as quo] + (:require [clojure.string :as string] + [quo.core :as quo] + [react-native.core :as rn] [status-im.common.not-implemented :as not-implemented] - [utils.i18n :as i18n])) + [status-im.contexts.profile.contact.add-nickname.view :as add-nickname] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) (defn view [] - [quo/action-drawer - [[{:icon :i/edit - :label (i18n/label :t/add-nickname-title) - :on-press not-implemented/alert - :accessibility-label :add-nickname} - {:icon :i/qr-code - :label (i18n/label :t/show-qr) - :on-press not-implemented/alert - :accessibility-label :show-qr-code} - {:icon :i/share - :label (i18n/label :t/share-profile) - :on-press not-implemented/alert - :accessibility-label :share-profile} - {:icon :i/untrustworthy - :label (i18n/label :t/mark-untrustworthy) - :on-press not-implemented/alert - :accessibility-label :mark-untrustworthy - :add-divider? true - :danger? true} - {:icon :i/block - :label (i18n/label :t/block-user) - :on-press not-implemented/alert - :accessibility-label :block-user - :danger? true}]]]) + (let [{:keys [nickname public-key]} (rf/sub [:contacts/current-contact]) + on-add-nickname (rn/use-callback #(rf/dispatch [:show-bottom-sheet + {:content + (fn [] [add-nickname/view])}])) + on-remove-nickname (rn/use-callback + (fn [] + (rf/dispatch [:hide-bottom-sheet]) + (rf/dispatch [:toasts/upsert + {:id :remove-nickname + :type :positive + :text (i18n/label :t/nickname-removed)}]) + (rf/dispatch [:contacts/update-nickname public-key ""])) + [public-key]) + has-nickname? (rn/use-memo (fn [] (not (string/blank? nickname))) [nickname])] + [quo/action-drawer + [[{:icon :i/edit + :label (if has-nickname? + (i18n/label :t/edit-nickname) + (i18n/label :t/add-nickname-title)) + :on-press on-add-nickname + :accessibility-label (if nickname :edit-nickname :add-nickname)} + {:icon :i/qr-code + :label (i18n/label :t/show-qr) + :on-press not-implemented/alert + :accessibility-label :show-qr-code} + {:icon :i/share + :label (i18n/label :t/share-profile) + :on-press not-implemented/alert + :accessibility-label :share-profile} + (when has-nickname? + {:icon :i/delete + :label (i18n/label :t/remove-nickname) + :on-press on-remove-nickname + :add-divider? true + :accessibility-label :remove-nickname + :danger? true}) + {:icon :i/untrustworthy + :label (i18n/label :t/mark-untrustworthy) + :on-press not-implemented/alert + :accessibility-label :mark-untrustworthy + :add-divider? (when-not has-nickname? true) + :danger? true} + {:icon :i/block + :label (i18n/label :t/block-user) + :on-press not-implemented/alert + :accessibility-label :block-user + :danger? true}]]])) diff --git a/src/status_im/contexts/profile/contact/add_nickname/style.cljs b/src/status_im/contexts/profile/contact/add_nickname/style.cljs new file mode 100644 index 0000000000..53ed0fb9bc --- /dev/null +++ b/src/status_im/contexts/profile/contact/add_nickname/style.cljs @@ -0,0 +1,6 @@ +(ns status-im.contexts.profile.contact.add-nickname.style) + +(def input-wrapper + {:padding-vertical 8 + :padding-horizontal 20 + :gap 8}) diff --git a/src/status_im/contexts/profile/contact/add_nickname/view.cljs b/src/status_im/contexts/profile/contact/add_nickname/view.cljs new file mode 100644 index 0000000000..d15e904226 --- /dev/null +++ b/src/status_im/contexts/profile/contact/add_nickname/view.cljs @@ -0,0 +1,81 @@ +(ns status-im.contexts.profile.contact.add-nickname.view + (:require [clojure.string :as string] + [quo.core :as quo] + [react-native.core :as rn] + [status-im.common.validation.profile :as profile-validator] + [status-im.constants :as constants] + [status-im.contexts.profile.contact.add-nickname.style :as style] + [status-im.contexts.profile.utils :as profile.utils] + [utils.debounce :as debounce] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn view + [] + (let [{:keys [public-key primary-name nickname customization-color] + :as profile} (rf/sub [:contacts/current-contact]) + ;; TODO(@mohsen): remove :blue, https://github.com/status-im/status-mobile/issues/18733 + customization-color (or customization-color :blue) + full-name (profile.utils/displayed-name profile) + profile-picture (profile.utils/photo profile) + [unsaved-nickname set-unsaved-nickname] (rn/use-state nickname) + [error-msg set-error-msg] (rn/use-state nil) + validate-nickname (rn/use-callback + (debounce/debounce + (fn [name] + (set-error-msg + (profile-validator/validation-nickname name))) + 300)) + on-cancel (rn/use-callback #(rf/dispatch [:hide-bottom-sheet])) + on-nickname-change (rn/use-callback (fn [text] + (set-unsaved-nickname text) + (validate-nickname text))) + on-nickname-submit (rn/use-callback + (fn [] + (rf/dispatch [:hide-bottom-sheet]) + (rf/dispatch [:toasts/upsert + {:id :add-nickname + :type :positive + :text (i18n/label + (if (string/blank? nickname) + :t/nickname-added + :t/nickname-updated) + {:primary-name primary-name})}]) + (rf/dispatch [:contacts/update-nickname public-key + (string/trim unsaved-nickname)])) + [public-key unsaved-nickname])] + [:<> + [quo/drawer-top + {:type :context-tag + :context-tag-type :default + :title (i18n/label :t/add-nickname-title) + :full-name full-name + :profile-picture profile-picture + :customization-color customization-color}] + [rn/view {:style style/input-wrapper} + [quo/input + {:type :text + :char-limit constants/profile-name-max-length + :max-length constants/profile-name-max-length + :auto-focus true + :default-value unsaved-nickname + :error? (not (string/blank? error-msg)) + :label (i18n/label :t/nickname) + :on-change-text on-nickname-change} + :on-submit-editing on-nickname-submit] + [quo/info-message + {:icon :i/info + :size :default + :type (if-not (string/blank? error-msg) :error :default)} + (if-not (string/blank? error-msg) + error-msg + (i18n/label :t/nickname-visible-to-you))]] + [quo/bottom-actions + {:actions :two-actions + :button-one-label (i18n/label :t/add-nickname-title) + :button-one-props {:disabled? (or (string/blank? unsaved-nickname) + (not (string/blank? error-msg))) + :on-press on-nickname-submit} + :button-two-label (i18n/label :t/cancel) + :button-two-props {:type :grey + :on-press on-cancel}}]])) diff --git a/src/status_im/contexts/profile/contact/view.cljs b/src/status_im/contexts/profile/contact/view.cljs index ec6b857c4d..16e0a98753 100644 --- a/src/status_im/contexts/profile/contact/view.cljs +++ b/src/status_im/contexts/profile/contact/view.cljs @@ -21,7 +21,7 @@ {:navigate-back? true :height 148 :on-scroll #(reanimated/set-shared-value scroll-y %) - ;TODO remove colors/primary-50 when #18733 merged. + ;; TODO(@mohsen): remove colors/primary-50, https://github.com/status-im/status-mobile/issues/18733 :cover-color (or customization-color colors/primary-50) :background-color (colors/theme-colors colors/white colors/neutral-95 theme) :page-nav-props {:right-side [{:icon-name :i/options diff --git a/translations/en.json b/translations/en.json index 26d205f3c9..2ca00ee34b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1652,12 +1652,16 @@ "page-would-like-to-use-camera": "would like to use your camera", "page-camera-request-blocked": "camera requests blocked. To enable camera requests go to Settings", "nickname": "Nickname", + "nickname-is-too-long": "Nickname is too long", "add-nickname": "Add a nickname (optional)", "edit-nickname": "Edit nickname", "add-nickname-title": "Add nickname", "nickname-visible-to-you": "Nickname will only be visible to you", "type-nickname": "Type nickname", "remove-nickname": "Remove nickname", + "nickname-removed": "Nickname removed", + "nickname-added": "Nickname for {{primary-name}} added", + "nickname-updated": "Nickname for {{primary-name}} updated", "set-nickname-toast": "You have renamed {{primary-name}} as {{nickname}}", "remove-nickname-toast": "You have removed {{secondary-name}}'s nickname", "nickname-description": "Nicknames help you identify others in Status.\nOnly you can see the nicknames you’ve added",