From 94a3e266a95310ecc572a869cdb54c5d3e7fe9d3 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Wed, 1 Nov 2023 16:04:21 +0300 Subject: [PATCH] Edit derivation path (#17741) --- .../bottom_actions/component_spec.cljs | 10 +- .../drawers/bottom_actions/view.cljs | 39 +++--- .../quo_preview/drawers/bottom_actions.cljs | 33 +++-- .../contexts/quo_preview/preview.cljs | 6 +- .../common/network_preferences/view.cljs | 4 +- .../contexts/wallet/common/utils.cljs | 9 ++ .../edit_derivation_path/component_spec.cljs | 28 ++++ .../edit_derivation_path/style.cljs | 49 +++++++ .../edit_derivation_path/view.cljs | 120 ++++++++++++++++++ .../contexts/wallet/create_account/view.cljs | 11 +- src/status_im2/core_spec.cljs | 3 +- src/status_im2/navigation/screens.cljs | 4 + test/jest/jestSetup.js | 7 + translations/en.json | 9 +- 14 files changed, 294 insertions(+), 38 deletions(-) create mode 100644 src/status_im2/contexts/wallet/create_account/edit_derivation_path/component_spec.cljs create mode 100644 src/status_im2/contexts/wallet/create_account/edit_derivation_path/style.cljs create mode 100644 src/status_im2/contexts/wallet/create_account/edit_derivation_path/view.cljs diff --git a/src/quo/components/drawers/bottom_actions/component_spec.cljs b/src/quo/components/drawers/bottom_actions/component_spec.cljs index 95dee663ef..b21bb0dd77 100644 --- a/src/quo/components/drawers/bottom_actions/component_spec.cljs +++ b/src/quo/components/drawers/bottom_actions/component_spec.cljs @@ -18,13 +18,19 @@ (h/render [bottom-actions/view {:actions :2-actions :button-one-label button-one + :button-one-props {:icon-left :i/arrow-left} :button-two-label button-two}]) (h/is-truthy (h/get-by-text button-one)) + (h/is-truthy (h/get-by-label-text :icon)) (h/is-truthy (h/get-by-text button-two)))) (h/test "render disabled button" (h/render [bottom-actions/view {:description "Sample description" - :disabled? true + :button-one-props {:disabled? true} :button-one-label "button"}]) - (h/is-disabled (h/get-by-label-text :button-one)))) + (h/is-disabled (h/get-by-label-text :button-one))) + + (h/test "sane defaults" + (h/render [bottom-actions/view {}]) + (h/is-truthy (h/get-by-label-text :button-one)))) diff --git a/src/quo/components/drawers/bottom_actions/view.cljs b/src/quo/components/drawers/bottom_actions/view.cljs index 75c657c326..ea1d100fe7 100644 --- a/src/quo/components/drawers/bottom_actions/view.cljs +++ b/src/quo/components/drawers/bottom_actions/view.cljs @@ -17,34 +17,35 @@ :description - string (default nil) - Description to display below the title :button-one-label - string (default nil) - Label for the first button :button-two-label - string (default nil) - Label for the second button - :button-one-press - fn (default nil) - Function to call when the first button is pressed - :button-two-press - fn (default nil) - Function to call when the second button is pressed + :button-one-props - map with props for button one + :button-two-props - map with props for button two :theme - :light/:dark - :scroll - bool (default false) - Whether the iOS Home Indicator should be rendered - :button-one-type - same as button/button :type - :button-two-type - same as button/button :type" + :scroll? - bool (default false) - Whether the iOS Home Indicator should be rendered" [props] (let [{:keys [actions description button-one-label button-two-label - button-one-press button-two-press theme - scroll? button-one-type button-two-type disabled?]} + button-one-props button-two-props theme scroll?]} (merge default-props props)] [:<> [rn/view {:style style/buttons-container} (when (= actions :2-actions) [button/button - {:size 40 - :background (when scroll? :blur) - :container-style style/button-container-2-actions - :type button-two-type - :on-press button-two-press} button-two-label]) + (merge + {:size 40 + :background (when scroll? :blur) + :container-style style/button-container-2-actions + :theme theme + :accessibility-label :button-two} + button-two-props) + button-two-label]) [button/button - {:size 40 - :container-style style/button-container - :type button-one-type - :disabled? disabled? - :background (when scroll? :blur) - :on-press button-one-press - :accessibility-label :button-one} button-one-label]] + (merge + {:size 40 + :container-style style/button-container + :background (when scroll? :blur) + :theme theme + :accessibility-label :button-one} + button-one-props) + button-one-label]] (when description [text/text {:size :paragraph-2 diff --git a/src/status_im2/contexts/quo_preview/drawers/bottom_actions.cljs b/src/status_im2/contexts/quo_preview/drawers/bottom_actions.cljs index bbd2fffe57..46ceb9c8fd 100644 --- a/src/status_im2/contexts/quo_preview/drawers/bottom_actions.cljs +++ b/src/status_im2/contexts/quo_preview/drawers/bottom_actions.cljs @@ -21,12 +21,24 @@ :key :actions :options [{:key :1-action} {:key :2-actions}]} - {:type :select - :key :button-two-type - :options button-options} - {:type :select - :key :button-one-type - :options button-options} + {:label "Button 1 type" + :type :select + :key :type + :options button-options + :path [:button-one-props]} + {:label "Button 1 disabled?" + :type :boolean + :key :disabled? + :path [:button-one-props]} + {:label "Button 2 type" + :type :select + :key :type + :options button-options + :path [:button-two-props]} + {:label "Button 2 disabled?" + :type :boolean + :key :disabled? + :path [:button-two-props]} {:key :description :type :text} {:key :button-one-label @@ -42,10 +54,11 @@ :description description :button-one-label button-one :button-two-label button-two - :button-one-press (button-press 2) - :button-two-press (button-press 1) - :button-one-type :primary - :button-two-type :grey + :button-one-props {:on-press (button-press 1) + :type :primary + :icon-left :i/arrow-up} + :button-two-props {:on-press (button-press 2) + :type :grey} :scroll? false})] (fn [] [preview/preview-container diff --git a/src/status_im2/contexts/quo_preview/preview.cljs b/src/status_im2/contexts/quo_preview/preview.cljs index 59f6770536..3d233075dc 100644 --- a/src/status_im2/contexts/quo_preview/preview.cljs +++ b/src/status_im2/contexts/quo_preview/preview.cljs @@ -258,7 +258,11 @@ :padding-horizontal 20}} (doall (for [desc descriptors - :let [descriptor (merge desc {:state state})]] + :let [desc-path (:path desc) + new-state (if desc-path + (reagent/cursor state desc-path) + state) + descriptor (assoc desc :state new-state)]] ^{:key (:key desc)} [:<> (case (:type desc) diff --git a/src/status_im2/contexts/wallet/common/network_preferences/view.cljs b/src/status_im2/contexts/wallet/common/network_preferences/view.cljs index 8083260516..73840282de 100644 --- a/src/status_im2/contexts/wallet/common/network_preferences/view.cljs +++ b/src/status_im2/contexts/wallet/common/network_preferences/view.cljs @@ -56,7 +56,7 @@ :data networks-list}] [quo/bottom-actions {:button-one-label (i18n/label :t/update) - :disabled? true - :button-one-press on-save}]]) + :button-one-props {:disabled? true + :on-press on-save}}]]) (def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im2/contexts/wallet/common/utils.cljs b/src/status_im2/contexts/wallet/common/utils.cljs index a3e97a057c..bde23b73ff 100644 --- a/src/status_im2/contexts/wallet/common/utils.cljs +++ b/src/status_im2/contexts/wallet/common/utils.cljs @@ -24,3 +24,12 @@ (defn get-derivation-path [number-of-accounts] (str constants/path-wallet-root "/" number-of-accounts)) + +(defn format-derivation-path + [path] + (string/replace path "/" " / ")) + +(defn get-formatted-derivation-path + [number-of-accounts] + (let [path (get-derivation-path number-of-accounts)] + (format-derivation-path path))) diff --git a/src/status_im2/contexts/wallet/create_account/edit_derivation_path/component_spec.cljs b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/component_spec.cljs new file mode 100644 index 0000000000..3047e28a2f --- /dev/null +++ b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/component_spec.cljs @@ -0,0 +1,28 @@ +(ns status-im2.contexts.wallet.create-account.edit-derivation-path.component-spec + (:require + [status-im2.contexts.wallet.create-account.edit-derivation-path.view :as edit-derivation-path] + [test-helpers.component :as h])) + +(h/describe "Edit derivation path page" + (h/test "Default render" + (h/render [edit-derivation-path/view {}]) + (h/is-truthy (h/get-by-translation-text :t/edit-derivation-path)) + (h/is-truthy (h/get-by-translation-text :t/path-format)) + (h/is-truthy (h/get-by-translation-text :t/derivation-path)) + (h/is-truthy (h/get-by-translation-text :t/reveal-address)) + (h/is-truthy (h/get-by-translation-text :t/save))) + + + (h/test "Reveal address pressed" + (let [on-reveal (h/mock-fn)] + (h/render [edit-derivation-path/view {:on-reveal on-reveal}]) + (h/fire-event :press (h/get-by-translation-text :t/reveal-address)) + (h/was-called on-reveal) + (h/wait-for #(h/is-truthy (h/get-by-translation-text :t/address-activity))))) + + (h/test "Reset button pressed" + (let [on-reset (h/mock-fn)] + (h/render [edit-derivation-path/view {:on-reset on-reset}]) + (h/fire-event :press (h/get-by-translation-text :t/reset)) + (h/was-called on-reset) + (h/wait-for #(h/is-truthy (h/get-by-translation-text :t/derive-addresses)))))) diff --git a/src/status_im2/contexts/wallet/create_account/edit_derivation_path/style.cljs b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/style.cljs new file mode 100644 index 0000000000..82b928498e --- /dev/null +++ b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/style.cljs @@ -0,0 +1,49 @@ +(ns status-im2.contexts.wallet.create-account.edit-derivation-path.style + (:require [quo.foundations.colors :as colors])) + +(defn screen + [top] + {:flex 1 + :margin-top top}) + +(def header + {:padding-horizontal 20 + :padding-top 12 + :padding-bottom 8}) + +(def tag + {:padding-horizontal 20 + :flex-direction :row}) + +(def input-container + {:padding-horizontal 20 + :padding-top 12}) + +(defn save-button-container + [bottom] + {:flex 1 + :justify-content :flex-end + :padding-bottom bottom}) + +(def revealed-address-container + {:padding-horizontal 20 + :padding-top 24}) + +(defn revealed-address + [theme] + {:border-width 1 + :border-color (colors/resolve-color :success theme 40) + :border-style :dashed + :border-radius 16 + :padding-horizontal 12 + :padding-vertical 7}) + +(def info + {:margin-vertical 9 + :padding-left 2}) + +(def temporal-placeholder + {:height 94 + :background-color colors/danger-50 + :align-items :center + :justify-content :center}) diff --git a/src/status_im2/contexts/wallet/create_account/edit_derivation_path/view.cljs b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/view.cljs new file mode 100644 index 0000000000..ba69ba8f0b --- /dev/null +++ b/src/status_im2/contexts/wallet/create_account/edit_derivation_path/view.cljs @@ -0,0 +1,120 @@ +(ns status-im2.contexts.wallet.create-account.edit-derivation-path.view + (:require + [quo.core :as quo] + [quo.theme :as quo.theme] + [react-native.core :as rn] + [react-native.safe-area :as safe-area] + [reagent.core :as reagent] + [status-im2.contexts.wallet.common.temp :as temp] + [status-im2.contexts.wallet.common.utils :as utils] + [status-im2.contexts.wallet.create-account.edit-derivation-path.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn- view-internal + "States: + default(filled) + | -> (reveal-action) -> show + | -> (clear-action) -> empty -> (derive-action) -> choose -> (choose-action) -> show" + [{:keys [on-reset on-reveal]}] + (let [top (safe-area/get-top) + bottom (safe-area/get-bottom) + state (reagent/atom :default) + reveal-action (fn [_] + (reset! state :show) + (when on-reveal + (on-reveal))) + clear-action #(reset! state :empty) + derive-action #(reset! state :choose) + choose-action #(reset! state :show) + path-value (reagent/atom (utils/get-formatted-derivation-path 3)) + handle-path-change (fn [v] + (reset! path-value v) + (when (empty? v) + (clear-action))) + reset-path-value (fn [_] + (reset! path-value "") + (clear-action) + (when on-reset + (on-reset)))] + (fn [{:keys [theme]}] + [rn/view + {:style (style/screen top)} + [quo/page-nav + {:background :blur + :icon-name :i/close + :on-press #(rf/dispatch [:navigate-back])}] + [quo/text + {:size :heading-1 + :weight :semi-bold + :style style/header} + (i18n/label :t/edit-derivation-path)] + [rn/view {:style style/tag} + [quo/context-tag + {:type :icon + :size 24 + :icon :i/placeholder + :style style/tag + :context "Alisher Card"}]] + [rn/view {:style style/temporal-placeholder} + [quo/text "Dropdown input will be here"] + [quo/text (i18n/label :t/path-format)]] + [quo/input + {:container-style style/input-container + :value @path-value + :label (i18n/label :t/derivation-path) + :placeholder (utils/get-formatted-derivation-path 3) + :button {:on-press reset-path-value + :text (i18n/label :t/reset)} + :on-change-text handle-path-change}] + + (case @state + :default + [quo/bottom-actions + {:theme theme + :actions :1-action + :button-one-label (i18n/label :t/reveal-address) + :button-one-props {:type :outline + :icon-left :i/keycard-card + :on-press reveal-action}}] + + :empty + [quo/bottom-actions + {:theme theme + :actions :1-action + :button-one-label (i18n/label :t/derive-addresses) + :button-one-props {:type :outline + :icon-left :i/keycard-card + :on-press derive-action}}] + + :show + [rn/view {:style style/revealed-address-container} + [rn/view {:style (style/revealed-address theme)} + [quo/text + {:weight :monospace} + temp/address]] + [quo/info-message + {:type :success + :icon :i/done + :style style/info} + (i18n/label :t/address-activity)]] + + :choose + [rn/view {:style style/temporal-placeholder} + [quo/text "Dropdown input will be here"] + [quo/button + {:on-press (fn [_] + (reset! path-value (utils/get-formatted-derivation-path 1)) + (choose-action))} "Choose"]] + nil) + + [rn/view {:style (style/save-button-container bottom)} + [quo/bottom-actions + {:theme theme + :actions :1-action + :button-one-label (i18n/label :t/save) + :button-one-props {:type :primary + :on-press #(js/alert "Save!") + :disabled? true}}]]]))) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im2/contexts/wallet/create_account/view.cljs b/src/status_im2/contexts/wallet/create_account/view.cljs index 6e5a737129..023e276575 100644 --- a/src/status_im2/contexts/wallet/create_account/view.cljs +++ b/src/status_im2/contexts/wallet/create_account/view.cljs @@ -21,12 +21,19 @@ (defn get-keypair-data [name derivation-path] [{:title (keypair-string name) - :button-props {:title (i18n/label :t/edit)} :left-icon :i/placeholder + :action :button + :action-props {:on-press #(js/alert "Button pressed!") + :button-text (i18n/label :t/edit) + :alignment :flex-start} :description :text :description-props {:text (i18n/label :t/on-device)}} {:title (i18n/label :t/derivation-path) - :button-props {:title (i18n/label :t/edit)} + :action :button + :action-props {:on-press #(rf/dispatch [:navigate-to :wallet-edit-derivation-path]) + :button-text (i18n/label :t/edit) + :icon-left :i/placeholder + :alignment :flex-start} :left-icon :i/derivated-path :description :text :description-props {:text derivation-path}}]) diff --git a/src/status_im2/core_spec.cljs b/src/status_im2/core_spec.cljs index 7b0415425a..46ba6b2c24 100644 --- a/src/status_im2/core_spec.cljs +++ b/src/status_im2/core_spec.cljs @@ -1,4 +1,5 @@ (ns status-im2.core-spec (:require [status-im2.contexts.chat.messages.content.audio.component-spec] - [status-im2.contexts.communities.actions.community-options.component-spec])) + [status-im2.contexts.communities.actions.community-options.component-spec] + [status-im2.contexts.wallet.create-account.edit-derivation-path.component-spec])) diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index 91a929b247..98212cb407 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -40,6 +40,7 @@ [status-im2.contexts.wallet.account.view :as wallet-accounts] [status-im2.contexts.wallet.address-watch.view :as wallet-address-watch] [status-im2.contexts.wallet.collectible.view :as wallet-collectible] + [status-im2.contexts.wallet.create-account.edit-derivation-path.view :as wallet-edit-derivation-path] [status-im2.contexts.wallet.create-account.view :as wallet-create-account] [status-im2.contexts.wallet.edit-account.view :as wallet-edit-account] [status-im2.contexts.wallet.saved-address.view :as wallet-saved-address] @@ -258,6 +259,9 @@ {:name :wallet-create-account :component wallet-create-account/view} + {:name :wallet-edit-derivation-path + :component wallet-edit-derivation-path/view} + {:name :wallet-saved-address :component wallet-saved-address/view} diff --git a/test/jest/jestSetup.js b/test/jest/jestSetup.js index ccb0b9e983..5c15317265 100644 --- a/test/jest/jestSetup.js +++ b/test/jest/jestSetup.js @@ -78,6 +78,13 @@ jest.mock('react-native-blob-util', () => ({ jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock')); +jest.mock('react-native-static-safe-area-insets', () => ({ + default: { + safeAreaInsetsTop: 0, + safeAreaInsetsBottom: 0, + }, +})); + NativeModules.ReactLocalization = { language: 'en', locale: 'en', diff --git a/translations/en.json b/translations/en.json index 65df21ed3f..ae0328c04c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2366,5 +2366,12 @@ "network-preferences-desc": "Select which network this address is happy to receive funds on", "layer-2": "Layer 2", "manage-tokens": "Manage tokens", - "sign transactions": "sign transactions" + "sign transactions": "sign transactions", + "edit-derivation-path": "Edit derivation path", + "path-format": "Path format", + "derivation-path": "Derivation path", + "reset": "Reset", + "reveal-address": "Reveal address", + "derive-addresses": "Derive addresses", + "address-activity": "This address has activity" }