diff --git a/src/quo/components/common/new_feature_dot.cljs b/src/quo/components/common/new_feature_dot.cljs new file mode 100644 index 0000000000..00c8614fa1 --- /dev/null +++ b/src/quo/components/common/new_feature_dot.cljs @@ -0,0 +1,13 @@ +(ns quo.components.common.new-feature-dot + (:require [quo.components.common.new-feature-gradient :as new-feature-gradient])) + +(def ^:const size 8) + +(defn view + [{:keys [style accessibility-label]}] + [new-feature-gradient/view + {:style (merge {:width size + :height size + :border-radius (/ size 2)} + style) + :accessibility-label accessibility-label}]) diff --git a/src/quo/components/common/new_feature_gradient.cljs b/src/quo/components/common/new_feature_gradient.cljs new file mode 100644 index 0000000000..6dd95fa54a --- /dev/null +++ b/src/quo/components/common/new_feature_gradient.cljs @@ -0,0 +1,16 @@ +(ns quo.components.common.new-feature-gradient + (:require [quo.foundations.colors :as colors] + [quo.theme] + [react-native.linear-gradient :as linear-gradient])) + +(defn view + [{:keys [style accessibility-label]}] + (let [theme (quo.theme/use-theme)] + [linear-gradient/linear-gradient + {:style style + :accessibility-label accessibility-label + :colors [(colors/resolve-color :yellow theme) + colors/new-feature-gradient-pink] + :use-angle true + :angle 78 + :angle-center {:x 0.5 :y 0.5}}])) diff --git a/src/quo/components/dropdowns/network_dropdown/component_spec.cljs b/src/quo/components/dropdowns/network_dropdown/component_spec.cljs index fbd6090d0d..206ab5d6a9 100644 --- a/src/quo/components/dropdowns/network_dropdown/component_spec.cljs +++ b/src/quo/components/dropdowns/network_dropdown/component_spec.cljs @@ -33,4 +33,12 @@ networks-list]) (h/is-truthy (h/query-by-label-text :network-dropdown)) (h/fire-event :press (h/query-by-label-text :network-dropdown)) - (h/was-not-called on-press)))) + (h/was-not-called on-press))) + + (h/test "Should display new chain indicator" + (h/render [network-dropdown/view + {:state :default + :show-new-chain-indicator? true} + networks-list]) + (h/is-truthy (h/query-by-label-text :network-dropdown)) + (h/is-truthy (h/query-by-label-text :new-chain-indicator)))) diff --git a/src/quo/components/dropdowns/network_dropdown/style.cljs b/src/quo/components/dropdowns/network_dropdown/style.cljs index cb0efe2b57..a1116fc486 100644 --- a/src/quo/components/dropdowns/network_dropdown/style.cljs +++ b/src/quo/components/dropdowns/network_dropdown/style.cljs @@ -23,3 +23,7 @@ :opacity (if (= state :disabled) 0.3 1) :border-color (container-border-color props) :align-items :center}) + +(def new-chain-indicator + {:position :absolute + :right 0}) diff --git a/src/quo/components/dropdowns/network_dropdown/view.cljs b/src/quo/components/dropdowns/network_dropdown/view.cljs index adf9b34aef..33cf9a6516 100644 --- a/src/quo/components/dropdowns/network_dropdown/view.cljs +++ b/src/quo/components/dropdowns/network_dropdown/view.cljs @@ -1,12 +1,13 @@ (ns quo.components.dropdowns.network-dropdown.view (:require + [quo.components.common.new-feature-dot :as new-feature-dot] [quo.components.dropdowns.network-dropdown.style :as style] [quo.components.list-items.preview-list.view :as preview-list] [quo.theme :as quo.theme] [react-native.core :as rn])) (defn view - [{:keys [on-press state] :as props} networks] + [{:keys [on-press state show-new-chain-indicator?] :as props} networks] (let [theme (quo.theme/use-theme) [pressed? set-pressed] (rn/use-state false) on-press-in (rn/use-callback #(set-pressed true)) @@ -18,6 +19,10 @@ :on-press on-press :on-press-in on-press-in :on-press-out on-press-out} + (when show-new-chain-indicator? + [new-feature-dot/view + {:style style/new-chain-indicator + :accessibility-label :new-chain-indicator}]) [preview-list/view {:type :network :list-size (count networks) diff --git a/src/quo/components/navigation/page_nav/view.cljs b/src/quo/components/navigation/page_nav/view.cljs index 8bf9ebf12a..ec53fa585f 100644 --- a/src/quo/components/navigation/page_nav/view.cljs +++ b/src/quo/components/navigation/page_nav/view.cljs @@ -200,12 +200,15 @@ shown-name]])) (defn- wallet-networks-center - [{:keys [networks networks-on-press background center-content-container-style]}] + [{:keys [networks networks-on-press show-new-chain-indicator? background + center-content-container-style]}] [reanimated/view {:style center-content-container-style} [network-dropdown/view - {:state :default - :on-press networks-on-press - :blur? (= background :blur)} networks]]) + {:state :default + :on-press networks-on-press + :blur? (= background :blur) + :show-new-chain-indicator? show-new-chain-indicator?} + networks]]) (defn page-nav "Props: diff --git a/src/quo/components/settings/settings_item/style.cljs b/src/quo/components/settings/settings_item/style.cljs index 19b3ff9bcc..e707deecbc 100644 --- a/src/quo/components/settings/settings_item/style.cljs +++ b/src/quo/components/settings/settings_item/style.cljs @@ -64,3 +64,20 @@ {:margin-top 7 :margin-bottom 2 :margin-left -1}) + +(def new-feature-tag-container + {:margin-left 6 + :border-radius 12 + :justify-content :center}) + +(def new-feature-tag-gradient + {:border-radius 12 + :position :absolute + :left 0 + :right 0 + :top 0 + :bottom 0}) + +(def new-feature-tag-text + {:color colors/white + :margin-horizontal 5}) diff --git a/src/quo/components/settings/settings_item/view.cljs b/src/quo/components/settings/settings_item/view.cljs index 70a109a34b..17a4b1b0ab 100644 --- a/src/quo/components/settings/settings_item/view.cljs +++ b/src/quo/components/settings/settings_item/view.cljs @@ -4,6 +4,7 @@ [quo.components.avatars.icon-avatar :as icon-avatar] [quo.components.avatars.user-avatar.view :as user-avatar] [quo.components.buttons.button.view :as button] + [quo.components.common.new-feature-gradient :as new-feature-gradient] [quo.components.icon :as icon] [quo.components.list-items.preview-list.view :as preview-list] [quo.components.markdown.text :as text] @@ -115,7 +116,9 @@ nil)]) (defn view - [{:keys [title on-press action-props accessibility-label blur? container-style content] :as props}] + [{:keys [title show-new-feature-tag? on-press action-props accessibility-label blur? container-style + content] + :as props}] [rn/pressable {:style (merge style/container container-style) :on-press (or on-press (:on-change action-props)) @@ -126,10 +129,19 @@ [rn/view {:style (style/left-sub-container props)} [image-component props] [rn/view {:style (style/left-container (:image props))} - [text/text - {:weight :medium - :style {:color (when blur? colors/white)}} - title] + [rn/view {:flex-direction :row} + [text/text + {:weight :medium + :style {:color (when blur? colors/white)}} + title] + (when show-new-feature-tag? + [rn/view {:style style/new-feature-tag-container} + [new-feature-gradient/view {:style style/new-feature-tag-gradient}] + [text/text + {:weight :semi-bold + :size :label + :style style/new-feature-tag-text} + (string/upper-case (i18n/label :t/new))]])] [description-component props] [tag-component props]]] [rn/view {:style (style/sub-container (:alignment action-props))} diff --git a/src/quo/components/wallet/wallet_overview/schema.cljs b/src/quo/components/wallet/wallet_overview/schema.cljs index c2ed3f383f..e0cfdf8134 100644 --- a/src/quo/components/wallet/wallet_overview/schema.cljs +++ b/src/quo/components/wallet/wallet_overview/schema.cljs @@ -18,5 +18,6 @@ [:dropdown-on-press {:optional true} [:maybe fn?]] [:networks {:optional true} [:maybe [:sequential [:map [:source [:maybe :schema.common/image-source]]]]]] - [:dropdown-state {:optional true} [:maybe [:enum :default :disabled]]]]]] + [:dropdown-state {:optional true} [:maybe [:enum :default :disabled]]] + [:show-new-chain-indicator? {:optional true} [:maybe :boolean]]]]] :any]) diff --git a/src/quo/components/wallet/wallet_overview/view.cljs b/src/quo/components/wallet/wallet_overview/view.cljs index 1312046e50..88f7a97aba 100644 --- a/src/quo/components/wallet/wallet_overview/view.cljs +++ b/src/quo/components/wallet/wallet_overview/view.cljs @@ -25,7 +25,7 @@ bars)) (defn- view-info-top - [{:keys [state balance networks dropdown-on-press dropdown-state]}] + [{:keys [state balance networks dropdown-on-press dropdown-state show-new-chain-indicator?]}] (let [theme (quo.theme/use-theme)] [rn/view {:style style/container-info-top} (if (= state :loading) @@ -36,9 +36,10 @@ :style (style/style-text-heading theme)} balance]) [network-dropdown/view - {:state (or dropdown-state :default) - :blur? true - :on-press dropdown-on-press} + {:state (or dropdown-state :default) + :blur? true + :on-press dropdown-on-press + :show-new-chain-indicator? show-new-chain-indicator?} networks]])) (defn- view-metrics diff --git a/src/quo/foundations/colors.cljs b/src/quo/foundations/colors.cljs index 6d5cab9faa..c6ee95acf6 100644 --- a/src/quo/foundations/colors.cljs +++ b/src/quo/foundations/colors.cljs @@ -315,6 +315,8 @@ networks-short-name socials)) +(def new-feature-gradient-pink "#FF33A3") + (defn hex-string? [s] (and (string? s) (string/starts-with? s "#"))) diff --git a/src/status_im/contexts/wallet/common/account_switcher/view.cljs b/src/status_im/contexts/wallet/common/account_switcher/view.cljs index df8c7874d5..5c000a9ea0 100644 --- a/src/status_im/contexts/wallet/common/account_switcher/view.cljs +++ b/src/status_im/contexts/wallet/common/account_switcher/view.cljs @@ -1,6 +1,7 @@ (ns status-im.contexts.wallet.common.account-switcher.view (:require [quo.core :as quo] + [react-native.core :as rn] [status-im.contexts.wallet.sheets.account-options.view :as account-options] [status-im.contexts.wallet.sheets.network-filter.view :as network-filter] [status-im.contexts.wallet.sheets.select-account.view :as select-account] @@ -30,25 +31,33 @@ type :no-title}}] (let [{:keys [color emoji watch-only?]} (rf/sub [:wallet/current-viewing-account]) networks (rf/sub [:wallet/selected-network-details]) - sending-collectible? (rf/sub [:wallet/sending-collectible?])] + sending-collectible? (rf/sub [:wallet/sending-collectible?]) + show-new-chain-indicator? (rf/sub [:wallet/show-new-chain-indicator?]) + on-press-networks (rn/use-callback + (fn [] + (rf/dispatch [:wallet/hide-new-chain-indicator]) + (rf/dispatch [:show-bottom-sheet + {:content network-filter/view}])))] [quo/page-nav - {:type type - :icon-name icon-name - :margin-top margin-top - :background :blur - :on-press on-press - :accessibility-label accessibility-label - :networks networks - :align-center? true - :networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}]) - :right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect) - (not watch-only?) - show-dapps-button?) - {:icon-name :i/dapps - :on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])}) - (when-not sending-collectible? - {:content-type :account-switcher - :customization-color color - :on-press #(on-switcher-press switcher-type params) - :emoji emoji - :type (when watch-only? :watch-only)})]}])) + {:type type + :icon-name icon-name + :margin-top margin-top + :background :blur + :on-press on-press + :accessibility-label accessibility-label + :networks networks + :align-center? true + :networks-on-press on-press-networks + :show-new-chain-indicator? show-new-chain-indicator? + :right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect) + (not watch-only?) + show-dapps-button?) + {:icon-name :i/dapps + :on-press #(rf/dispatch [:navigate-to + :screen/wallet.connected-dapps])}) + (when-not sending-collectible? + {:content-type :account-switcher + :customization-color color + :on-press #(on-switcher-press switcher-type params) + :emoji emoji + :type (when watch-only? :watch-only)})]}])) diff --git a/src/status_im/contexts/wallet/common/utils.cljs b/src/status_im/contexts/wallet/common/utils.cljs index 18ecd88c7a..c5e26c0938 100644 --- a/src/status_im/contexts/wallet/common/utils.cljs +++ b/src/status_im/contexts/wallet/common/utils.cljs @@ -324,20 +324,19 @@ (defn make-network-item "This function generates props for quo/category component item" - [{:keys [network-name color on-change networks state label-props type blur?]}] - (cond-> {:title (string/capitalize (name network-name)) - :image :icon-avatar - :image-props {:icon (resources/get-network network-name) - :size :size-20} - :action :selector - :action-props {:type (or type - (if (= :default state) - :filled-checkbox - :checkbox)) - :blur? blur? - :customization-color color - :checked? (contains? networks network-name) - :on-change on-change}} + [{:keys [network-name color on-change networks label-props type blur?]}] + (cond-> {:title (string/capitalize (name network-name)) + :image :icon-avatar + :image-props {:icon (resources/get-network network-name) + :size :size-20} + ;; Remove the following line for v2.35 + :show-new-feature-tag? (= network-name constants/base-network-name) + :action :selector + :action-props {:type (or type :checkbox) + :blur? blur? + :customization-color color + :checked? (contains? networks network-name) + :on-change on-change}} label-props (assoc :label :text diff --git a/src/status_im/contexts/wallet/effects.cljs b/src/status_im/contexts/wallet/effects.cljs index c5d6f38a78..a378da6e35 100644 --- a/src/status_im/contexts/wallet/effects.cljs +++ b/src/status_im/contexts/wallet/effects.cljs @@ -3,6 +3,7 @@ [clojure.string :as string] [native-module.core :as native-module] [promesa.core :as promesa] + [react-native.async-storage :as async-storage] [status-im.common.json-rpc.events :as json-rpc] [status-im.contexts.profile.recover.effects :as profile.recover.effects] [status-im.contexts.wallet.rpc :as wallet-rpc] @@ -130,3 +131,14 @@ (-> (wallet-rpc/sign-message message address (security/safe-unmask-data password)) (promesa/then on-success) (promesa/catch on-error)))) + +(rf/reg-fx + :effects.wallet/retrieve-base-chain-indicator-shown + (fn [] + (async-storage/get-item :base-chain-indicator-shown + #(rf/dispatch [:wallet/retrieve-new-chain-indicator (not %)])))) + +(rf/reg-fx + :effects.wallet/set-base-chain-indicator-shown + (fn [flag] + (async-storage/set-item! :base-chain-indicator-shown flag))) diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index 629bf3b6b1..203f805297 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -797,3 +797,14 @@ :wallet.swap/transaction-success :wallet/transaction-success) sent-transactions])]]}))) + +(rf/reg-event-fx + :wallet/retrieve-new-chain-indicator + (fn [{:keys [db]} [flag]] + {:db (assoc-in db [:wallet :ui :show-new-chain-indicator?] flag)})) + +(rf/reg-event-fx + :wallet/hide-new-chain-indicator + (fn [{:keys [db]}] + {:db (assoc-in db [:wallet :ui :show-new-chain-indicator?] false) + :fx [[:effects.wallet/set-base-chain-indicator-shown true]]})) diff --git a/src/status_im/contexts/wallet/home/view.cljs b/src/status_im/contexts/wallet/home/view.cljs index b7ac9ce39e..8064148356 100644 --- a/src/status_im/contexts/wallet/home/view.cljs +++ b/src/status_im/contexts/wallet/home/view.cljs @@ -135,7 +135,13 @@ cards (conj account-cards-data (new-account-card-data)) [init-loaded? set-init-loaded] (rn/use-state false) {:keys [formatted-balance]} (rf/sub [:wallet/aggregated-token-values-and-balance]) - theme (quo.theme/use-theme)] + theme (quo.theme/use-theme) + show-new-chain-indicator? (rf/sub [:wallet/show-new-chain-indicator?]) + on-press-network-selector (rn/use-callback + (fn [] + (rf/dispatch [:wallet/hide-new-chain-indicator]) + (rf/dispatch [:show-bottom-sheet + {:content network-filter/view}])))] (rn/use-effect (fn [] (when (and @account-list-ref (pos? (count cards))) (.scrollToOffset ^js @account-list-ref @@ -157,13 +163,14 @@ :on-refresh #(rf/dispatch [:wallet/get-accounts])}] :header [rn/view {:style (style/header-container theme)} [quo/wallet-overview - {:state (if tokens-loading? :loading :default) - :time-frame :none - :metrics :none - :balance formatted-balance - :networks networks - :dropdown-on-press #(rf/dispatch [:show-bottom-sheet - {:content network-filter/view}])}] + {:state (if tokens-loading? :loading :default) + :time-frame :none + :metrics :none + :balance formatted-balance + :networks networks + :dropdown-on-press on-press-network-selector + :show-new-chain-indicator? (when (not-empty networks) + show-new-chain-indicator?)}] (when (ff/enabled? ::ff/wallet.graph) [quo/wallet-graph {:time-frame :empty}]) [render-cards cards account-list-ref] diff --git a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs index 2123c33cfd..2e685fbc1a 100644 --- a/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs +++ b/src/status_im/contexts/wallet/send/input_amount/component_spec.cljs @@ -18,6 +18,7 @@ :network-name :mainnet :chain-id 1 :related-chain-id 5}] + :wallet/show-new-chain-indicator? false :wallet/current-viewing-account-address "0x1" :wallet/current-viewing-account {:path "m/44'/60'/0'/0/1" :emoji "💎" diff --git a/src/status_im/contexts/wallet/sheets/network_filter/view.cljs b/src/status_im/contexts/wallet/sheets/network_filter/view.cljs index e14aa23446..8a5ade1d32 100644 --- a/src/status_im/contexts/wallet/sheets/network_filter/view.cljs +++ b/src/status_im/contexts/wallet/sheets/network_filter/view.cljs @@ -8,41 +8,26 @@ (defn view [] (let [selected-networks (rf/sub [:wallet/selected-networks]) - selector-state (rf/sub [:wallet/network-filter-selector-state]) color (rf/sub [:profile/customization-color]) - network-details (rf/sub [:wallet/network-details]) - viewing-account? (rf/sub [:wallet/viewing-account?]) - balance-per-chain (if viewing-account? - (rf/sub [:wallet/current-viewing-account-fiat-balance-per-chain]) - (rf/sub [:wallet/aggregated-fiat-balance-per-chain])) - mainnet (first network-details) - layer-2-networks (rest network-details)] + network-details (rf/sub [:wallet/network-details])] [:<> [quo/drawer-top {:title (i18n/label :t/select-networks)}] + [quo/information-box + {:type :informative + :icon :i/info + :blur? false + :style {:margin-horizontal 20 + :margin-bottom 4}} + (i18n/label :t/base-chain-available-info)] [quo/category {:list-type :settings - :data [(utils/make-network-item - {:state selector-state - :network-name (:network-name mainnet) - :color color - :networks selected-networks - :label-props (get balance-per-chain (:chain-id mainnet)) - :on-change #(rf/dispatch - [:wallet/update-selected-networks - (:network-name - mainnet)])})]}] - [quo/category - {:list-type :settings - :label (i18n/label :t/layer-2) :data (mapv (fn [network] (utils/make-network-item - {:state selector-state - :network-name (:network-name network) + {:network-name (:network-name network) :color color :networks selected-networks - :label-props (get balance-per-chain (:chain-id network)) :on-change #(rf/dispatch [:wallet/update-selected-networks (:network-name network)])})) - layer-2-networks)}]])) + network-details)}]])) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index e44a114cc3..332bb1e77d 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -78,4 +78,6 @@ ;;app starting flow continues in get-profiles-overview :profile/get-profiles-overview #(rf/dispatch [:profile/get-profiles-overview-success %]) :effects.font/get-font-file-for-initials-avatar - #(rf/dispatch [:font/init-font-file-for-initials-avatar %])})) + #(rf/dispatch [:font/init-font-file-for-initials-avatar %]) + ;; show new chain indicator to highlight base chain. This will be be removed in v2.35. + :effects.wallet/retrieve-base-chain-indicator-shown nil})) diff --git a/src/status_im/subs/wallet/wallet.cljs b/src/status_im/subs/wallet/wallet.cljs index 41dddf8d1c..7bff19a025 100644 --- a/src/status_im/subs/wallet/wallet.cljs +++ b/src/status_im/subs/wallet/wallet.cljs @@ -47,6 +47,11 @@ :<- [:wallet/ui] :-> :last-updates-per-address) +(rf/reg-sub + :wallet/show-new-chain-indicator? + :<- [:wallet/ui] + :-> :show-new-chain-indicator?) + (rf/reg-sub :wallet/latest-update :<- [:wallet/last-updates-per-address] diff --git a/test/appium/tests/critical/wallet/test_collectibles.py b/test/appium/tests/critical/wallet/test_collectibles.py index 03dc4c8262..7cff9c236c 100644 --- a/test/appium/tests/critical/wallet/test_collectibles.py +++ b/test/appium/tests/critical/wallet/test_collectibles.py @@ -41,7 +41,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase): @marks.testrail_id(741839) def test_wallet_collectibles_balance(self): self.wallet_view.collectibles_tab.click() - self.wallet_view.set_network_in_wallet(self.network_name) + self.wallet_view.set_network_in_wallet(self.network_name + ', NEW') collectibles = { "BVL": {"quantity": 2, "info": {"Account": "Account 1", diff --git a/test/appium/tests/critical/wallet/test_wallet_mainnet.py b/test/appium/tests/critical/wallet/test_wallet_mainnet.py index f61b84a9c1..a89225d8fb 100644 --- a/test/appium/tests/critical/wallet/test_wallet_mainnet.py +++ b/test/appium/tests/critical/wallet/test_wallet_mainnet.py @@ -52,7 +52,7 @@ class TestWalletOneDevice(MultipleSharedDeviceTestCase): 'Mainnet': self.mainnet_balance, 'Arbitrum': self.arb_balance, 'Optimism': self.optimism_balance, - 'Base': self.base_balance + 'Base, NEW': self.base_balance } for network in expected_balances: diff --git a/test/appium/views/wallet_view.py b/test/appium/views/wallet_view.py index a36d99dbdb..cd220d48ed 100644 --- a/test/appium/views/wallet_view.py +++ b/test/appium/views/wallet_view.py @@ -182,7 +182,7 @@ class WalletView(BaseView): def set_network_in_wallet(self, network_name: str): self.network_drop_down.click() - Button(self.driver, accessibility_id="%s, label-component" % network_name.capitalize()).click() + Button(self.driver, accessibility_id="%s, label-component" % network_name).click() self.network_drop_down.click() def get_account_element(self, account_name: str = 'Account 1'): diff --git a/translations/en.json b/translations/en.json index 19ac9038bf..685eeee7fc 100644 --- a/translations/en.json +++ b/translations/en.json @@ -200,6 +200,7 @@ "bad-fees-description": "Your priority fee is below our suggested parameters.", "balance": "Balance", "base": "Base", + "base-chain-available-info": "Base chain is now on Status - view your assets, interact with dApps and swap tokens", "be-safe-with-secure-cold-wallet": "Be safe with secure cold wallet", "begin-set-up": "Begin setup", "below-base-fee": "max fee below base fee",