From f9f328107d22eb9da92ab706e3858a0bc179ce3e Mon Sep 17 00:00:00 2001 From: Jamie Caprani Date: Fri, 1 Dec 2023 12:29:01 +0000 Subject: [PATCH] chore: add ability to create watch address & some related ui changes on account page (#17868) --- .../avatars/account_avatar/view.cljs | 2 +- .../avatars/channel_avatar/view.cljs | 2 +- .../avatars/wallet_user_avatar/view.cljs | 2 +- .../wallet/account_overview/view.cljs | 2 +- src/status_im2/common/bottom_sheet/view.cljs | 2 +- .../wallet/account/tabs/about/view.cljs | 55 ++++------- .../contexts/wallet/account/view.cljs | 36 ++++--- .../confirm_address/component_spec.cljs | 26 +++++ .../confirm_address/view.cljs | 11 ++- .../wallet/add_address_to_watch/style.cljs | 3 +- src/status_im2/contexts/wallet/events.cljs | 98 ++++++++++--------- src/status_im2/core_spec.cljs | 1 + src/status_im2/subs/wallet/wallet.cljs | 4 +- 13 files changed, 137 insertions(+), 107 deletions(-) create mode 100644 src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/component_spec.cljs diff --git a/src/quo/components/avatars/account_avatar/view.cljs b/src/quo/components/avatars/account_avatar/view.cljs index 156330b242..570ea5fe9a 100644 --- a/src/quo/components/avatars/account_avatar/view.cljs +++ b/src/quo/components/avatars/account_avatar/view.cljs @@ -30,6 +30,6 @@ {:accessibility-label :account-emoji :adjusts-font-size-to-fit true :style {:font-size emoji-size}} - (string/trim emoji)]])) + (when emoji (string/trim emoji))]])) (def view (quo.theme/with-theme view-internal)) diff --git a/src/quo/components/avatars/channel_avatar/view.cljs b/src/quo/components/avatars/channel_avatar/view.cljs index 437770c19c..7858bacd2e 100644 --- a/src/quo/components/avatars/channel_avatar/view.cljs +++ b/src/quo/components/avatars/channel_avatar/view.cljs @@ -67,7 +67,7 @@ [rn/text {:style (style/emoji-size size) :accessibility-label :emoji} - (string/trim emoji)]) + (when emoji (string/trim emoji))]) [lock locked? size theme]]) (def view (quo.theme/with-theme view-internal)) diff --git a/src/quo/components/avatars/wallet_user_avatar/view.cljs b/src/quo/components/avatars/wallet_user_avatar/view.cljs index d78aa51b08..2c39204344 100644 --- a/src/quo/components/avatars/wallet_user_avatar/view.cljs +++ b/src/quo/components/avatars/wallet_user_avatar/view.cljs @@ -56,6 +56,6 @@ :size (:font-size (size properties)) :weight (if monospace? :monospace (:font-weight (size properties))) :style (style/text customization-color neutral? theme)} - (if lowercase? (string/lower-case initials) initials)]])) + (if (and initials lowercase?) (string/lower-case initials) initials)]])) (def wallet-user-avatar (quo.theme/with-theme view-internal)) diff --git a/src/quo/components/wallet/account_overview/view.cljs b/src/quo/components/wallet/account_overview/view.cljs index 671ae59b43..c5744afe3c 100644 --- a/src/quo/components/wallet/account_overview/view.cljs +++ b/src/quo/components/wallet/account_overview/view.cljs @@ -133,7 +133,7 @@ | key | description | | -------------|-------------| | `:account-name` | A value representing the account name (default `nil`) - | `:account` | A value that represents if the account is a `:watched-account` or a `:default` account. (default `nil`) + | `:account` | A value that represents if the account is a `:watched-address` or a `:default` account. (default `nil`) | `:time-frame` | A value that represents the type of the timeframe, Can be from a preset of time frames. `[:1-week :1-month :3-months :1-year :custom]` (default `nil`) if custom is set, We expect a start time and if there's a space between two times that are in `time-frame-string` we'll split them with an arrow to the right icon | `:loading?` | A value that indicates that component is loading data. (default `nil`) | `:metrics` | A value that indicates if the account value have increased can be `:positive` or `:negative` (default `nil`) diff --git a/src/status_im2/common/bottom_sheet/view.cljs b/src/status_im2/common/bottom_sheet/view.cljs index 368afe4071..ea58c7d5d7 100644 --- a/src/status_im2/common/bottom_sheet/view.cljs +++ b/src/status_im2/common/bottom_sheet/view.cljs @@ -117,7 +117,7 @@ [rn/view {:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin) :on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))} - (when gradient-cover? + (when (and gradient-cover? customization-color) [rn/view {:style style/gradient-bg} [quo/gradient-cover {:customization-color customization-color diff --git a/src/status_im2/contexts/wallet/account/tabs/about/view.cljs b/src/status_im2/contexts/wallet/account/tabs/about/view.cljs index 01fe38a390..942d16bdda 100644 --- a/src/status_im2/contexts/wallet/account/tabs/about/view.cljs +++ b/src/status_im2/contexts/wallet/account/tabs/about/view.cljs @@ -1,31 +1,12 @@ (ns status-im2.contexts.wallet.account.tabs.about.view (:require [quo.core :as quo] - [quo.foundations.colors :as colors] - [quo.theme :as quo.theme] [react-native.core :as rn] [status-im2.contexts.wallet.account.tabs.about.style :as style] [status-im2.contexts.wallet.common.temp :as temp] [utils.i18n :as i18n] [utils.re-frame :as rf])) -(defn description - [{:keys [address theme]}] - (let [networks-list (rf/sub [:wallet/network-details])] - [quo/text {:size :paragraph-2} - (map (fn [{:keys [chain-id short-name network-name]}] - ^{:key (str chain-id short-name)} - [quo/text - {:size :paragraph-2 - :weight :medium - :style {:color (colors/resolve-color network-name theme)}} - (str short-name ":")]) - networks-list) - [quo/text - {:size :paragraph-2 - :weight :monospace} - address]])) - (defn about-options [] [quo/action-drawer @@ -51,19 +32,25 @@ :accessibility-label :share-address :label (i18n/label :t/share-address)}]]]) -(defn- view-internal +(defn view [] - [rn/view {:style style/about-tab} - [quo/data-item - (merge temp/data-item-state - {:custom-subtitle (fn [] [quo/address-text - {:networks [{:network-name :ethereum :short-name "eth"} - {:network-name :optimism :short-name "opt"} - {:network-name :arbitrum :short-name "arb1"}] - :address temp/address - :format :long}]) - :container-style {:margin-bottom 12} - :on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])})] - [quo/account-origin temp/account-origin-state]]) - -(def view (quo.theme/with-theme view-internal)) + (let [{:keys [type address]} (rf/sub [:wallet/current-viewing-account]) + networks (rf/sub [:wallet/network-details]) + watch-only? (= type :watch)] + [rn/view {:style style/about-tab} + [quo/data-item + {:description :default + :icon-right? true + :right-icon :i/options + :card? true + :label :none + :status :default + :size :default + :title (if watch-only? (i18n/label :t/watched-address) (i18n/label :t/address)) + :custom-subtitle (fn [] [quo/address-text + {:networks networks + :address address + :format :long}]) + :container-style {:margin-bottom 12} + :on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])}] + (when (not watch-only?) [quo/account-origin temp/account-origin-state])])) diff --git a/src/status_im2/contexts/wallet/account/view.cljs b/src/status_im2/contexts/wallet/account/view.cljs index 16b41c60b3..fc26b174af 100644 --- a/src/status_im2/contexts/wallet/account/view.cljs +++ b/src/status_im2/contexts/wallet/account/view.cljs @@ -21,37 +21,41 @@ :padding-bottom 8} :render-fn quo/settings-item}]]) -(def tabs-data - [{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab} - {:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab} - {:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab} - {:id :dapps :label (i18n/label :t/dapps) :accessibility-label :dapps} - {:id :about :label (i18n/label :t/about) :accessibility-label :about}]) +(def first-tab-id :assets) + +(defn tabs-data + [watch-only?] + (cond-> [{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab} + {:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab} + {:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}] + (not watch-only?) (conj {:id :dapps :label (i18n/label :t/dapps) :accessibility-label :dapps}) + true (conj {:id :about :label (i18n/label :t/about) :accessibility-label :about}))) (defn view [] - (let [selected-tab (reagent/atom (:id (first tabs-data)))] + (let [selected-tab (reagent/atom first-tab-id)] (fn [] - (let [{:keys [name color balance]} (rf/sub [:wallet/current-viewing-account]) - ] + (let [{:keys [name color balance type]} (rf/sub [:wallet/current-viewing-account]) + watch-only? (= type :watch)] [rn/view {:style {:flex 1}} [account-switcher/view {:on-press #(rf/dispatch [:wallet/close-account-page])}] [quo/account-overview {:current-value (utils/prettify-balance balance) :account-name name - :account :default + :account (if watch-only? :watched-address :default) :customization-color color}] [quo/wallet-graph {:time-frame :empty}] - [quo/wallet-ctas - {:send-action #(rf/dispatch [:open-modal :wallet-select-address]) - :buy-action #(rf/dispatch [:show-bottom-sheet - {:content buy-drawer}]) - :bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}] + (when (not watch-only?) + [quo/wallet-ctas + {:send-action #(rf/dispatch [:open-modal :wallet-select-address]) + :buy-action #(rf/dispatch [:show-bottom-sheet + {:content buy-drawer}]) + :bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}]) [quo/tabs {:style style/tabs :size 32 :default-active @selected-tab - :data tabs-data + :data (tabs-data watch-only?) :on-change #(reset! selected-tab %) :scrollable? true :scroll-on-press? true}] diff --git a/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/component_spec.cljs b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/component_spec.cljs new file mode 100644 index 0000000000..66905ec94a --- /dev/null +++ b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/component_spec.cljs @@ -0,0 +1,26 @@ +(ns status-im2.contexts.wallet.add-address-to-watch.confirm-address.component-spec + (:require + [re-frame.core :as re-frame] + [status-im2.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address] + [test-helpers.component :as h] + [utils.re-frame :as rf])) + +(defn setup-subs + [subscriptions] + (doseq [keyval subscriptions] + (re-frame/reg-sub + (key keyval) + (fn [_] (val keyval))))) + +(h/describe "Add Watch Only Account Page" + (h/test "Create Account button is disabled while no account name exists" + (let [callback (h/mock-fn)] + (with-redefs [rf/dispatch #(callback)] + (setup-subs {:profile/wallet-accounts [] + :get-screen-params {:address "0xmock-address"}}) + (h/render [confirm-address/view {}]) + (h/is-truthy (h/get-by-text "0xmock-address")) + (h/was-not-called callback) + (h/fire-event :change-text (h/get-by-label-text :profile-title-input) "NAME") + (h/fire-event :press (h/get-by-translation-text :t/add-watched-address)) + (h/was-called callback))))) diff --git a/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs index 1efd47c967..0fc3fa041c 100644 --- a/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs +++ b/src/status_im2/contexts/wallet/add_address_to_watch/confirm_address/view.cljs @@ -3,7 +3,6 @@ [clojure.string :as string] [quo.core :as quo] [quo.foundations.colors :as colors] - [re-frame.core :as re-frame] [react-native.core :as rn] [reagent.core :as reagent] [status-im2.contexts.emoji-picker.utils :as emoji-picker.utils] @@ -43,8 +42,14 @@ :bottom-action-label :t/add-watched-address :bottom-action-props {:customization-color @account-color :disabled? (string/blank? @account-name) - :on-press #(re-frame/dispatch [:navigate-to - :wallet-account])}} + :on-press #(rf/dispatch [:wallet/add-account + nil + {:type :watch + :account-name @account-name + :emoji @account-emoji + :color @account-color} + {:address address + :public-key ""}])}} [quo/data-item {:card? true :right-icon :i/advanced diff --git a/src/status_im2/contexts/wallet/add_address_to_watch/style.cljs b/src/status_im2/contexts/wallet/add_address_to_watch/style.cljs index 1b01f32705..4dc271f798 100644 --- a/src/status_im2/contexts/wallet/add_address_to_watch/style.cljs +++ b/src/status_im2/contexts/wallet/add_address_to_watch/style.cljs @@ -6,8 +6,7 @@ :margin-bottom 20}) (def scan - {:align-self - :flex-end}) + {:margin-top 26}) (def input {:flex 1 diff --git a/src/status_im2/contexts/wallet/events.cljs b/src/status_im2/contexts/wallet/events.cljs index 64f932c9c2..8394d46d92 100644 --- a/src/status_im2/contexts/wallet/events.cljs +++ b/src/status_im2/contexts/wallet/events.cljs @@ -18,23 +18,32 @@ (rf/reg-event-fx :wallet/show-account-created-toast (fn [{:keys [db]} [address]] - (let [{:keys [name]} (get-in db [:wallet :accounts address])] + (let [account (get-in db [:wallet :accounts address])] {:db (update db :wallet dissoc :navigate-to-account :new-account?) :fx [[:dispatch [:toasts/upsert {:id :new-wallet-account-created :icon :i/correct :icon-color colors/success-50 - :text (i18n/label :t/account-created {:name name})}]]]}))) + :text (i18n/label :t/account-created {:name (:name account)})}]]]}))) (rf/reg-event-fx :wallet/navigate-to-account (fn [{:keys [db]} [address]] - (let [new-account? (get-in db [:wallet :new-account?])] - (cond-> {:db (assoc-in db [:wallet :current-viewing-account-address] address) - :fx [[:dispatch [:navigate-to :wallet-accounts address]]]} + {:db (assoc-in db [:wallet :current-viewing-account-address] address) + :fx [[:dispatch [:navigate-to :wallet-accounts address]]]})) - new-account? - (update :fx conj [:dispatch [:wallet/show-account-created-toast address]]))))) +(rf/reg-event-fx :wallet/navigate-to-new-account + (fn [{:keys [db]} [address]] + {:db (assoc-in db [:wallet :current-viewing-account-address] address) + :fx [[:dispatch [:hide-bottom-sheet]] + [:dispatch-later + [{:dispatch [:navigate-back] + :ms 100} + {:dispatch [:navigate-back] + :ms 100} + {:dispatch [:navigate-to :wallet-accounts address] + :ms 300}]] + [:dispatch [:wallet/show-account-created-toast address]]]})) (rf/reg-event-fx :wallet/close-account-page (fn [{:keys [db]}] @@ -44,24 +53,17 @@ (rf/reg-event-fx :wallet/get-accounts-success (fn [{:keys [db]} [accounts]] - (let [wallet-db (get db :wallet) + (let [wallet-accounts (filter #(not (:chat %)) accounts) + wallet-db (get db :wallet) new-account? (:new-account? wallet-db) navigate-to-account (:navigate-to-account wallet-db)] - (cond-> {:db (reduce (fn [db {:keys [address] :as account}] - (assoc-in db [:wallet :accounts address] account)) - db - (data-store/rpc->accounts accounts)) - :fx [[:dispatch [:wallet/get-wallet-token]]]} - - new-account? - (update :fx - conj - [:dispatch [:hide-bottom-sheet]] - [:dispatch-later - [{:dispatch [:navigate-back] - :ms 100} - {:dispatch [:wallet/navigate-to-account navigate-to-account] - :ms 300}]]))))) + {:db (reduce (fn [db {:keys [address] :as account}] + (assoc-in db [:wallet :accounts address] account)) + db + (data-store/rpc->accounts wallet-accounts)) + :fx [[:dispatch [:wallet/get-wallet-token]] + (when new-account? + [:dispatch [:wallet/navigate-to-new-account navigate-to-account]])]}))) (rf/reg-event-fx :wallet/get-accounts @@ -144,29 +146,35 @@ :on-success on-success :on-error #(log/info "failed to derive address " %)}]]]}))) -(rf/reg-event-fx - :wallet/add-account - (fn [{:keys [db]} [password {:keys [emoji account-name color]} {:keys [public-key address path]}]] - (let [key-uid (get-in db [:profile/profile :key-uid]) - sha3-pwd (native-module/sha3 (security/safe-unmask-data password)) - account-config {:key-uid key-uid - :wallet false - :chat false - :type :generated - :name account-name - :emoji emoji - :path path - :address address - :public-key public-key - :colorID color}] - {:db (update db - :wallet assoc - :navigate-to-account address - :new-account? true) - :fx [[:json-rpc/call +(rf/reg-event-fx :wallet/add-account-success + (fn [{:keys [db]} [address]] + {:db (update db + :wallet assoc + :navigate-to-account address + :new-account? true) + :fx [[:dispatch [:wallet/get-accounts]]]})) + +(rf/reg-event-fx :wallet/add-account + (fn [{:keys [db]} + [password {:keys [emoji account-name color type] :or {type :generated}} + {:keys [public-key address path]}]] + (let [lowercase-address (if address (string/lower-case address) address) + key-uid (get-in db [:profile/profile :key-uid]) + sha3-pwd (native-module/sha3 (security/safe-unmask-data password)) + account-config {:key-uid (when (= type :generated) key-uid) + :wallet false + :chat false + :type type + :name account-name + :emoji emoji + :path path + :address lowercase-address + :public-key public-key + :colorID color}] + {:fx [[:json-rpc/call [{:method "accounts_addAccount" - :params [sha3-pwd account-config] - :on-success [:wallet/get-accounts] + :params [(when (= type :generated) sha3-pwd) account-config] + :on-success [:wallet/add-account-success lowercase-address] :on-error #(log/info "failed to create account " %)}]]]}))) (rf/reg-event-fx diff --git a/src/status_im2/core_spec.cljs b/src/status_im2/core_spec.cljs index 00a3092561..2af59e4e3a 100644 --- a/src/status_im2/core_spec.cljs +++ b/src/status_im2/core_spec.cljs @@ -4,5 +4,6 @@ [status-im2.contexts.chat.messages.content.audio.component-spec] [status-im2.contexts.communities.actions.community-options.component-spec] [status-im2.contexts.wallet.add-address-to-watch.component-spec] + [status-im2.contexts.wallet.add-address-to-watch.confirm-address.component-spec] [status-im2.contexts.wallet.create-account.edit-derivation-path.component-spec] [status-im2.contexts.wallet.send.input-amount.component-spec])) diff --git a/src/status_im2/subs/wallet/wallet.cljs b/src/status_im2/subs/wallet/wallet.cljs index a219d0ffed..d95f3f9a3a 100644 --- a/src/status_im2/subs/wallet/wallet.cljs +++ b/src/status_im2/subs/wallet/wallet.cljs @@ -48,10 +48,10 @@ :<- [:wallet/balances] :<- [:wallet/tokens-loading?] (fn [[accounts balances tokens-loading?]] - (mapv (fn [{:keys [color address] :as account}] + (mapv (fn [{:keys [color address type] :as account}] (assoc account :customization-color color - :type :empty + :type (if (= type :watch) :watch-only :empty) :on-press #(rf/dispatch [:wallet/navigate-to-account address]) :loading? tokens-loading? :balance (utils/prettify-balance (get balances address))))