From e38cb0dee6428d3ee855b92f769763db80d67295 Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Tue, 4 Feb 2025 14:50:42 -0300 Subject: [PATCH] feat: elevate and highlight wallet CTAs on wallet home screen (#21985) Signed-off-by: Brian Sztamfater --- src/status_im/contexts/shell/share/view.cljs | 91 ++++++++++--------- src/status_im/contexts/wallet/events.cljs | 16 ++-- src/status_im/contexts/wallet/home/style.cljs | 5 + src/status_im/contexts/wallet/home/view.cljs | 58 ++++++++++++ .../contexts/wallet/send/events.cljs | 8 +- .../contexts/wallet/send/events_test.cljs | 15 +-- .../contexts/wallet/send/from/view.cljs | 18 ++-- .../contexts/wallet/swap/events.cljs | 19 ++-- .../wallet/swap/select_account/view.cljs | 11 ++- 9 files changed, 165 insertions(+), 76 deletions(-) diff --git a/src/status_im/contexts/shell/share/view.cljs b/src/status_im/contexts/shell/share/view.cljs index d0abbb4b94..a666a8d116 100644 --- a/src/status_im/contexts/shell/share/view.cljs +++ b/src/status_im/contexts/shell/share/view.cljs @@ -11,56 +11,61 @@ (defn- header [] - [:<> - [rn/view {:style style/header-row} - [quo/button - {:icon-only? true - :type :grey - :background :blur - :size 32 - :accessibility-label :close-shell-share-tab - :container-style style/header-button - :on-press #(rf/dispatch [:navigate-back])} - :i/close] - [quo/button - {:icon-only? true - :type :grey - :background :blur - :size 32 - :accessibility-label :shell-scan-button - :on-press (fn [] - (rf/dispatch [:navigate-back]) - (rf/dispatch [:open-modal :shell-qr-reader]))} - :i/scan]] - [quo/text - {:size :heading-1 - :weight :semi-bold - :style style/header-heading} - (i18n/label :t/share)]]) + (let [{:keys [status]} (rf/sub [:get-screen-params])] + [:<> + [rn/view {:style style/header-row} + [quo/button + {:icon-only? true + :type :grey + :background :blur + :size 32 + :accessibility-label :close-shell-share-tab + :container-style style/header-button + :on-press #(rf/dispatch [:navigate-back])} + :i/close] + [quo/button + {:icon-only? true + :type :grey + :background :blur + :size 32 + :accessibility-label :shell-scan-button + :on-press (fn [] + (rf/dispatch [:navigate-back]) + (rf/dispatch [:open-modal :shell-qr-reader]))} + :i/scan]] + [quo/text + {:size :heading-1 + :weight :semi-bold + :style style/header-heading} + (if (= :receive status) + (i18n/label :t/receive) + (i18n/label :t/share))]])) (defn- tab-content - [initial-tab] - (let [[selected-tab set-selected-tab] (rn/use-state initial-tab)] + [] + (let [{:keys [initial-tab hide-tab-selector?] + :or {initial-tab :profile + hide-tab-selector? false}} (rf/sub [:get-screen-params]) + [selected-tab set-selected-tab] (rn/use-state initial-tab)] [rn/view {:style {:padding-top (safe-area/get-top)}} [header] - [rn/view {:style style/tabs-container} - [quo/segmented-control - {:size 28 - :blur? true - :on-change set-selected-tab - :default-active selected-tab - :data [{:id :profile - :label (i18n/label :t/profile)} - {:id :wallet - :label (i18n/label :t/wallet)}]}]] + (when-not hide-tab-selector? + [rn/view {:style style/tabs-container} + [quo/segmented-control + {:size 28 + :blur? true + :on-change set-selected-tab + :default-active selected-tab + :data [{:id :profile + :label (i18n/label :t/profile)} + {:id :wallet + :label (i18n/label :t/wallet)}]}]]) (if (= selected-tab :wallet) [wallet-view/wallet-tab] [profile-view/profile-tab])])) (defn view [] - (let [{:keys [initial-tab] :or {initial-tab :profile}} (rf/sub [:get-screen-params])] - [quo/overlay {:type :shell} - [rn/view - {:key :share} - [tab-content initial-tab]]])) + [quo/overlay {:type :shell} + [rn/view {:key :share} + [tab-content]]]) diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index f867618e11..7d857d04e8 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -433,13 +433,17 @@ [:wallet/bridge-select-token (assoc params :network network)]))}])}]]])}))) -(rf/reg-event-fx :wallet/start-bridge +(rf/reg-event-fx + :wallet/start-bridge (fn [{:keys [db]}] - {:db (assoc-in db [:wallet :ui :send :tx-type] :tx/bridge) - :fx [[:dispatch - [:wallet/wizard-navigate-forward - {:start-flow? true - :flow-id :wallet-bridge-flow}]]]})) + (let [view-id (:view-id db)] + (cond-> {:db (assoc-in db [:wallet :ui :send :tx-type] :tx/bridge)} + (= view-id :screen/wallet.accounts) + (assoc :fx + [[:dispatch + [:wallet/wizard-navigate-forward + {:start-flow? true + :flow-id :wallet-bridge-flow}]]]))))) (rf/reg-event-fx :wallet/select-bridge-network (fn [{:keys [db]} [{:keys [network-chain-id stack-id]}]] diff --git a/src/status_im/contexts/wallet/home/style.cljs b/src/status_im/contexts/wallet/home/style.cljs index 2727bc8af4..f8a62b2ef3 100644 --- a/src/status_im/contexts/wallet/home/style.cljs +++ b/src/status_im/contexts/wallet/home/style.cljs @@ -31,3 +31,8 @@ (defn header-container [theme] {:background-color (colors/theme-colors colors/white colors/neutral-95 theme)}) + +(def cta-buttons + {:padding-horizontal 20 + :padding-bottom 13 + :flex-direction :row}) diff --git a/src/status_im/contexts/wallet/home/view.cljs b/src/status_im/contexts/wallet/home/view.cljs index 77b453e9bf..133f19e74e 100644 --- a/src/status_im/contexts/wallet/home/view.cljs +++ b/src/status_im/contexts/wallet/home/view.cljs @@ -8,6 +8,7 @@ [status-im.common.refreshable-flat-list.view :as refreshable-flat-list] [status-im.contexts.wallet.home.style :as style] [status-im.contexts.wallet.home.tabs.view :as tabs] + [status-im.contexts.wallet.sheets.buy-token.view :as buy-token] [status-im.contexts.wallet.sheets.network-filter.view :as network-filter] [status-im.feature-flags :as ff] [utils.i18n :as i18n] @@ -64,6 +65,62 @@ :data data :on-change on-change}]) +(defn- call-to-actions + [] + (let [account-cards-data (rf/sub [:wallet/account-cards-data]) + testnet-mode? (rf/sub [:profile/test-networks-enabled?]) + multiple-accounts? (> (count account-cards-data) 1) + first-account-address (:address (first account-cards-data)) + on-send-press (rn/use-callback + (fn [] + (rf/dispatch [:wallet/clean-send-data]) + (when-not multiple-accounts? + (rf/dispatch [:wallet/switch-current-viewing-account + first-account-address])) + (if multiple-accounts? + (rf/dispatch [:open-modal :screen/wallet.select-from]) + (rf/dispatch [:wallet/wizard-navigate-forward + {:start-flow? true + :flow-id :wallet-send-flow}]))) + [multiple-accounts? first-account-address]) + on-receive-press (rn/use-callback #(rf/dispatch [:open-modal :screen/share-shell + {:initial-tab :wallet + :status :receive + :hide-tab-selector? true}])) + on-buy-press (rn/use-callback #(rf/dispatch [:show-bottom-sheet + {:content buy-token/view}])) + on-bridge-press (rn/use-callback + (fn [] + (rf/dispatch [:wallet/clean-send-data]) + (when-not multiple-accounts? + (rf/dispatch [:wallet/switch-current-viewing-account + first-account-address])) + (rf/dispatch [:wallet/start-bridge]) + (when multiple-accounts? + (rf/dispatch [:open-modal :screen/wallet.select-from]))) + [multiple-accounts? first-account-address]) + on-swap-press (rn/use-callback + (fn [] + (rf/dispatch [:wallet.tokens/get-token-list]) + (when-not multiple-accounts? + (rf/dispatch [:wallet/switch-current-viewing-account + first-account-address])) + (if multiple-accounts? + (rf/dispatch [:open-modal + :screen/wallet.swap-select-account]) + (rf/dispatch [:open-modal + :screen/wallet.swap-select-asset-to-pay]))) + [multiple-accounts? first-account-address])] + [quo/wallet-ctas + {:container-style style/cta-buttons + :send-action on-send-press + :receive-action on-receive-press + :buy-action on-buy-press + :bridge-action on-bridge-press + :swap-action on-swap-press + :bridge-disabled? testnet-mode? + :swap-disabled? testnet-mode?}])) + (defn view [] (let [selected-tab (rf/sub [:wallet/home-tab]) @@ -106,6 +163,7 @@ (when (ff/enabled? ::ff/wallet.graph) [quo/wallet-graph {:time-frame :empty}]) [render-cards cards account-list-ref] + [call-to-actions] [render-tabs tabs-data change-tab selected-tab]] :content-container-style style/list-container :sticky-header-indices [0] diff --git a/src/status_im/contexts/wallet/send/events.cljs b/src/status_im/contexts/wallet/send/events.cljs index a64e0af2f4..9003b6bc21 100644 --- a/src/status_im/contexts/wallet/send/events.cljs +++ b/src/status_im/contexts/wallet/send/events.cljs @@ -293,8 +293,9 @@ [:wallet :ui :send] dissoc :token - :token-symbol :token-display-name - :tx-type :network)})) + :token-symbol + :token-display-name + :network)})) (rf/reg-event-fx :wallet/clean-selected-collectible (fn [{:keys [db]} [{:keys [ignore-entry-point?]}]] @@ -740,6 +741,7 @@ token-symbol address)] (utils/token-with-balance token network-details))) + asset-selected? (or collectible-tx? (some? token)) bridge-tx? (= tx-type :tx/bridge) flow-id (if bridge-tx? :wallet-bridge-flow @@ -762,7 +764,7 @@ network (assoc-in [:wallet :ui :send :network] network) token-symbol (assoc-in [:wallet :ui :send :token] token) bridge-tx? (assoc-in [:wallet :ui :send :to-address] address)) - :fx (if (or no-tx-type? (some? network) collectible-tx?) + :fx (if (or no-tx-type? (some? network) collectible-tx? (not asset-selected?)) [[:dispatch [:wallet/switch-current-viewing-account address]] [:dispatch [:wallet/wizard-navigate-forward diff --git a/src/status_im/contexts/wallet/send/events_test.cljs b/src/status_im/contexts/wallet/send/events_test.cljs index fa98f05ec3..4ff0aa57e7 100644 --- a/src/status_im/contexts/wallet/send/events_test.cljs +++ b/src/status_im/contexts/wallet/send/events_test.cljs @@ -215,8 +215,7 @@ (reset! rf-db/app-db {:wallet {:ui {:send {:other-props :value :token "ETH" - :token-display-name "ETH" - :tx-type :tx/collectible-erc-721}}}}) + :token-display-name "ETH"}}}}) (is (match-strict? expected-db (:db (dispatch [event-id])))))) (h/deftest-event :wallet/clean-selected-collectible @@ -497,12 +496,16 @@ address "0x01" network {:chain-id 1}] (testing "when tx-type is :tx/bridge and token-symbol is nil" - (let [tx-type :tx/bridge + (let [flow-id :wallet-bridge-flow + tx-type :tx/bridge expected-result {:db {:wallet {:ui {:send {:to-address address :tx-type tx-type}}}} - :fx [[:dispatch [:dismiss-modal :screen/wallet.select-from]] - [:dispatch [:wallet/switch-current-viewing-account address]] - [:dispatch [:show-bottom-sheet {:content (m/pred fn?)}]]]}] + :fx [[:dispatch [:wallet/switch-current-viewing-account address]] + [:dispatch + [:wallet/wizard-navigate-forward + {:current-screen stack-id + :start-flow? start-flow? + :flow-id flow-id}]]]}] (reset! rf-db/app-db {:wallet {:ui {:send {:tx-type tx-type}}}}) (is (match? expected-result (dispatch [event-id diff --git a/src/status_im/contexts/wallet/send/from/view.cljs b/src/status_im/contexts/wallet/send/from/view.cljs index b7b6dab670..182d3711ca 100644 --- a/src/status_im/contexts/wallet/send/from/view.cljs +++ b/src/status_im/contexts/wallet/send/from/view.cljs @@ -14,14 +14,14 @@ [utils.re-frame :as rf])) (defn- on-account-press - [address general-flow? collectible-tx?] + [address general-flow? collectible-tx? token-selected?] (when general-flow? (rf/dispatch [:wallet/clean-selected-token]) (rf/dispatch [:wallet/clean-selected-collectible])) (rf/dispatch [:wallet/select-from-account {:address address :stack-id :screen/wallet.select-from - :start-flow? (not (or general-flow? collectible-tx?))}])) + :start-flow? (not (or general-flow? collectible-tx? token-selected?))}])) (defn- on-close [] @@ -29,7 +29,7 @@ (rf/dispatch [:wallet/clean-current-viewing-account])) (defn- render-fn - [item _ _ {:keys [general-flow? collectible-tx? collectible]}] + [item _ _ {:keys [general-flow? collectible-tx? collectible token]}] (let [account-address (:address item) balance (cond general-flow? 0 @@ -41,8 +41,13 @@ asset-value (if collectible-tx? (str balance) (:asset-pay-balance item))] [quo/account-item {:type (if has-balance? :tag :default) - :on-press #(on-account-press account-address general-flow? collectible-tx?) - :state (if (or has-balance? general-flow?) :default :disabled) + :on-press #(on-account-press account-address + general-flow? + collectible-tx? + (and (nil? collectible) (nil? token))) + :state (if (or has-balance? general-flow? (and (nil? collectible) (nil? token))) + :default + :disabled) :token-props (when-not general-flow? {:symbol asset-symbol :value asset-value}) @@ -77,6 +82,7 @@ :data accounts :render-data {:general-flow? general-flow? :collectible-tx? collectible-tx? - :collectible collectible} + :collectible collectible + :token token} :render-fn render-fn :shows-horizontal-scroll-indicator false}]])) diff --git a/src/status_im/contexts/wallet/swap/events.cljs b/src/status_im/contexts/wallet/swap/events.cljs index 31518a9ee7..1231c6c278 100644 --- a/src/status_im/contexts/wallet/swap/events.cljs +++ b/src/status_im/contexts/wallet/swap/events.cljs @@ -571,10 +571,15 @@ (fn [{:keys [db]} [account]] (let [asset-to-pay (get-in db [:wallet :ui :swap :asset-to-pay]) asset-to-receive (get-in db [:wallet :ui :swap :asset-to-receive])] - {:fx [[:dispatch [:dismiss-modal :screen/wallet.swap-select-account]] - [:dispatch - [:wallet.swap/start - {:asset-to-pay asset-to-pay - :asset-to-receive asset-to-receive - :open-new-screen? true - :from-account account}]]]}))) + {:fx (if asset-to-pay + [[:dispatch [:dismiss-modal :screen/wallet.swap-select-account]] + [:dispatch + [:wallet.swap/start + {:asset-to-pay asset-to-pay + :asset-to-receive asset-to-receive + :open-new-screen? true + :from-account account}]]] + [[:dispatch [:wallet/switch-current-viewing-account (:address account)]] + [:dispatch + [:navigate-to-within-stack + [:screen/wallet.swap-select-asset-to-pay :screen/wallet.swap-select-account]]]])}))) diff --git a/src/status_im/contexts/wallet/swap/select_account/view.cljs b/src/status_im/contexts/wallet/swap/select_account/view.cljs index 44a83f87cc..a2a96a1c69 100644 --- a/src/status_im/contexts/wallet/swap/select_account/view.cljs +++ b/src/status_im/contexts/wallet/swap/select_account/view.cljs @@ -11,16 +11,16 @@ [utils.re-frame :as rf])) (defn- on-account-press - [account] - (rf/dispatch [:wallet.swap/start-from-account account])) + [account asset-to-pay] + (rf/dispatch [:wallet.swap/start-from-account account asset-to-pay])) (defn- render-fn - [item _ _] + [item _ _ {:keys [asset-to-pay]}] (let [has-balance (money/above-zero? (:asset-pay-balance item))] [quo/account-item {:type (if has-balance :tag :default) - :on-press #(on-account-press item) - :state (if has-balance :default :disabled) + :on-press #(on-account-press item asset-to-pay) + :state (if (or has-balance (nil? asset-to-pay)) :default :disabled) :token-props {:symbol (:asset-pay-symbol item) :value (:asset-pay-balance item)} :account-props (assoc item @@ -49,5 +49,6 @@ {:style style/accounts-list :content-container-style style/accounts-list-container :data accounts + :render-data {:asset-to-pay asset-to-pay} :render-fn render-fn :shows-horizontal-scroll-indicator false}]]))