diff --git a/packages/trader/src/AppV2/Components/ActiveSymbolsList/active-symbols-list.tsx b/packages/trader/src/AppV2/Components/ActiveSymbolsList/active-symbols-list.tsx index 750cc6744f12..6730191262c5 100644 --- a/packages/trader/src/AppV2/Components/ActiveSymbolsList/active-symbols-list.tsx +++ b/packages/trader/src/AppV2/Components/ActiveSymbolsList/active-symbols-list.tsx @@ -33,7 +33,6 @@ const ActiveSymbolsList = observer(({ isOpen, setIsOpen }: TActiveSymbolsList) = setIsOpen(false)}> )} diff --git a/packages/trader/src/AppV2/Components/MarketCategories/__tests__/market-categories.spec.tsx b/packages/trader/src/AppV2/Components/MarketCategories/__tests__/market-categories.spec.tsx index 0b7207c8be8b..1f9e46c1dc56 100644 --- a/packages/trader/src/AppV2/Components/MarketCategories/__tests__/market-categories.spec.tsx +++ b/packages/trader/src/AppV2/Components/MarketCategories/__tests__/market-categories.spec.tsx @@ -20,6 +20,9 @@ describe('', () => { setSelectedSymbol: jest.fn(), setIsOpen: jest.fn(), isOpen: false, + marketCategoriesRef: { + current: document.createElement('div'), + }, }; beforeEach(() => { jest.clearAllMocks(); diff --git a/packages/trader/src/AppV2/Components/MarketCategories/market-categories.tsx b/packages/trader/src/AppV2/Components/MarketCategories/market-categories.tsx index 340b7cf64324..0961a49d72b7 100644 --- a/packages/trader/src/AppV2/Components/MarketCategories/market-categories.tsx +++ b/packages/trader/src/AppV2/Components/MarketCategories/market-categories.tsx @@ -1,21 +1,24 @@ -import React, { forwardRef, Ref } from 'react'; +import React from 'react'; import { Tab } from '@deriv-com/quill-ui'; import useActiveSymbols from 'AppV2/Hooks/useActiveSymbols'; import { categorizeSymbols } from 'AppV2/Utils/symbol-categories-utils'; import MarketCategory from '../MarketCategory'; import MarketCategoryTab from '../MarketCategoryTab/market-category-tab'; +import { observer } from '@deriv/stores'; type TMarketCategories = { selectedSymbol: string; setSelectedSymbol: (input: string) => void; setIsOpen: (input: boolean) => void; isOpen: boolean; + marketCategoriesRef: React.RefObject; }; -const MarketCategories = forwardRef( - ({ selectedSymbol, setSelectedSymbol, setIsOpen, isOpen }: TMarketCategories, ref: Ref) => { +const MarketCategories = observer( + ({ selectedSymbol, setSelectedSymbol, setIsOpen, isOpen, marketCategoriesRef }: TMarketCategories) => { const { activeSymbols } = useActiveSymbols(); const categorizedSymbols = categorizeSymbols(activeSymbols); + return ( @@ -23,7 +26,7 @@ const MarketCategories = forwardRef( ))} - + {Object.values(categorizedSymbols).map(category => ( { - if ( - isOpen && - category.market === 'all' && - selectedSymbol && - itemRefs.current[selectedSymbol] && - prevSymbol === selectedSymbol - ) { + if (isOpen && category.market === 'all' && selectedSymbol && itemRefs.current[selectedSymbol] && !prevSymbol) { timerRef.current = setTimeout(() => { itemRefs.current[selectedSymbol]?.scrollIntoView({ block: 'center' }); }, 50); diff --git a/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.scss b/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.scss index 487adcf28844..ce3ecd77fcbd 100644 --- a/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.scss +++ b/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.scss @@ -22,4 +22,10 @@ &--selected { background-color: var(--semantic-color-slate-solid-surface-inverse-lowest); } + &-left { + display: flex; + flex: 1 0 0; + align-items: center; + gap: var(--semantic-spacing-gap-lg); + } } diff --git a/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.tsx b/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.tsx index a0b2f1bb1c43..050e117202e1 100644 --- a/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.tsx +++ b/packages/trader/src/AppV2/Components/MarketCategoryItem/market-category-item.tsx @@ -8,6 +8,7 @@ import clsx from 'clsx'; import { observer, useStore } from '@deriv/stores'; import { useTraderStore } from 'Stores/useTraderStores'; import { useModulesStore } from 'Stores/useModulesStores'; +import { clickAndKeyEventHandler } from '@deriv/shared'; type TMarketCategoryItem = { item: ActiveSymbols[0]; @@ -30,15 +31,13 @@ const MarketCategoryItem = forwardRef( setIsFavorite(favoriteSymbols.includes(item.symbol)); }, [favoriteSymbols, item.symbol]); - const handleSelect = async (e: React.MouseEvent) => { - const symbol = (e.target as HTMLSpanElement).getAttribute('data-symbol'); - setSelectedSymbol(symbol ?? ''); + const handleSelect = async (symbol: string) => { + setSelectedSymbol(symbol); await onSymbolChange({ target: { name: 'symbol', value: symbol } }); setIsOpen(false); }; - const toggleFavorites = (e: React.MouseEvent) => { - const symbol = (e.currentTarget as HTMLSpanElement).getAttribute('data-symbol'); + const toggleFavorites = (symbol: string) => { if (!symbol) return; const symbolIndex = favoriteSymbols.indexOf(symbol); @@ -69,6 +68,16 @@ const MarketCategoryItem = forwardRef( setIsFavorite(favoriteSymbols.includes(symbol)); }; + const handleSelectDecorator = (e?: React.MouseEvent | React.KeyboardEvent) => { + const symbol = (e?.currentTarget as HTMLElement).getAttribute('data-symbol') || ''; + clickAndKeyEventHandler(() => handleSelect(symbol), e); + }; + + const toggleFavoritesDecorator = (e?: React.MouseEvent | React.KeyboardEvent) => { + const symbol = (e?.currentTarget as HTMLElement).getAttribute('data-symbol') || ''; + clickAndKeyEventHandler(() => toggleFavorites(symbol), e); + }; + return (
- - - - {item.display_name} - - - {!item.exchange_is_open && ( - } - color='error' - variant={selectedSymbol === item.symbol ? 'outline' : 'fill'} - showIcon={false} - /> - )} - + + + {item.display_name} + + {!item.exchange_is_open && ( + } + color='error' + variant={selectedSymbol === item.symbol ? 'outline' : 'fill'} + showIcon={false} + /> + )} + + {isFavorite ? ( ) : ( diff --git a/packages/trader/src/AppV2/Components/SymbolsSearchField/__tests__/symbols-search-field.spec.tsx b/packages/trader/src/AppV2/Components/SymbolsSearchField/__tests__/symbols-search-field.spec.tsx index 93f422865022..6c179776ee29 100644 --- a/packages/trader/src/AppV2/Components/SymbolsSearchField/__tests__/symbols-search-field.spec.tsx +++ b/packages/trader/src/AppV2/Components/SymbolsSearchField/__tests__/symbols-search-field.spec.tsx @@ -40,9 +40,6 @@ describe('', () => { setIsSearching: jest.fn(), searchValue: '', setSearchValue: jest.fn(), - marketCategoriesRef: { - current: document.createElement('div'), - }, }; jest.clearAllMocks(); }); diff --git a/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.scss b/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.scss index 1bffe896ce26..f04cf6b74898 100644 --- a/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.scss +++ b/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.scss @@ -7,7 +7,4 @@ &--is-focused { padding: var(--core-spacing-400) var(--core-spacing-400) var(--core-spacing-400) var(--core-spacing-800); } - &--is-hidden { - display: none; - } } diff --git a/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.tsx b/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.tsx index 6b0dbb8bec75..f54f277bd626 100644 --- a/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.tsx +++ b/packages/trader/src/AppV2/Components/SymbolsSearchField/symbols-search-field.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useEffect, useState, forwardRef, Ref } from 'react'; +import React, { useRef, useEffect } from 'react'; import { Button, SearchField } from '@deriv-com/quill-ui'; import clsx from 'clsx'; import { observer, useStore } from '@deriv/stores'; @@ -11,32 +11,15 @@ export type TSymbolsSearchField = { setIsSearching: (input: boolean) => void; searchValue: string; setSearchValue: (input: string) => void; - marketCategoriesRef: React.MutableRefObject; }; const SymbolsSearchField = observer( - ({ isSearching, setIsSearching, searchValue, setSearchValue, marketCategoriesRef }: TSymbolsSearchField) => { + ({ isSearching, setIsSearching, searchValue, setSearchValue }: TSymbolsSearchField) => { const { ui } = useStore(); const { is_dark_mode_on } = ui; const { contract_type } = useTraderStore(); const contract_name = getContractTypesConfig()[contract_type]?.title; const inputRef = useRef(null); - const [prevScrollY, setPrevScrollY] = useState(marketCategoriesRef.current?.scrollTop); - const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(true); - - useEffect(() => { - const handleScroll = () => { - const currentScrollY = marketCategoriesRef.current?.scrollTop; - - if (prevScrollY && currentScrollY !== null && currentScrollY !== undefined) - setIsSearchFieldVisible(prevScrollY > currentScrollY); - setPrevScrollY(currentScrollY); - }; - marketCategoriesRef.current?.addEventListener('scroll', handleScroll); - return () => { - marketCategoriesRef.current?.removeEventListener('scroll', handleScroll); - }; - }, [prevScrollY, marketCategoriesRef]); useEffect(() => { const inputElement = inputRef.current; @@ -61,7 +44,6 @@ const SymbolsSearchField = observer(
{ if ( (isVanillaContract(previous_contract_type) && is_vanilla) || - (isTurbosContract(previous_contract_type) && is_turbos) + (isTurbosContract(previous_contract_type) && is_turbos) || + getContractTypesList().length === 0 ) { return; } diff --git a/packages/trader/src/AppV2/Utils/sort-symbols-utils.ts b/packages/trader/src/AppV2/Utils/sort-symbols-utils.ts index c85218febfc6..affe6510269b 100644 --- a/packages/trader/src/AppV2/Utils/sort-symbols-utils.ts +++ b/packages/trader/src/AppV2/Utils/sort-symbols-utils.ts @@ -14,7 +14,7 @@ const sortSymbols = (symbolsList: ActiveSymbols) => { {} ); - return symbolsList.sort((a, b) => { + return symbolsList.slice().sort((a, b) => { const marketOrderA = marketOrderMap[a.market] !== undefined ? marketOrderMap[a.market] : symbolsList.length; const marketOrderB = marketOrderMap[b.market] !== undefined ? marketOrderMap[b.market] : symbolsList.length; if (marketOrderA !== marketOrderB) { diff --git a/packages/trader/src/AppV2/Utils/symbol-categories-utils.ts b/packages/trader/src/AppV2/Utils/symbol-categories-utils.ts index 428fe540e1b6..66b97a0c8e97 100644 --- a/packages/trader/src/AppV2/Utils/symbol-categories-utils.ts +++ b/packages/trader/src/AppV2/Utils/symbol-categories-utils.ts @@ -1,5 +1,6 @@ import { ActiveSymbols } from '@deriv/api-types'; import { localize } from '@deriv/translations'; +import sortSymbols from './sort-symbols-utils'; type SubmarketGroup = { submarket_display_name: string; @@ -22,7 +23,8 @@ export const categorizeSymbols = (symbols: ActiveSymbols): Record, symbol: ActiveSymbols[0]) => { + const sortedSymbols = sortSymbols(symbols); + let categorizedSymbols = sortedSymbols.reduce((acc: Record, symbol: ActiveSymbols[0]) => { const { market, market_display_name, subgroup, subgroup_display_name, submarket, submarket_display_name } = symbol; @@ -42,7 +44,6 @@ export const categorizeSymbols = (symbols: ActiveSymbols): Record { Object.keys(categorizedSymbols[market].subgroups).forEach(subgroup => { diff --git a/packages/trader/src/Stores/Modules/Trading/trade-store.ts b/packages/trader/src/Stores/Modules/Trading/trade-store.ts index 6e5d556f4096..69f5f9ce81d8 100644 --- a/packages/trader/src/Stores/Modules/Trading/trade-store.ts +++ b/packages/trader/src/Stores/Modules/Trading/trade-store.ts @@ -412,6 +412,7 @@ export default class TradeStore extends BaseStore { is_accumulator: computed, is_chart_loading: observable, is_digits_widget_active: observable, + is_dtrader_v2_enabled: computed, is_equal: observable, is_market_closed: observable, is_mobile_digit_view_selected: observable, @@ -664,8 +665,11 @@ export default class TradeStore extends BaseStore { async loadActiveSymbols(should_set_default_symbol = true, should_show_loading = true) { this.should_show_active_symbols_loading = should_show_loading; - await this.setActiveSymbols(); - await this.root_store.active_symbols.setActiveSymbols(); + if (!this.is_dtrader_v2_enabled) { + await this.setActiveSymbols(); + await this.root_store.active_symbols.setActiveSymbols(); + } + const { symbol, showModal } = getTradeURLParams({ active_symbols: this.active_symbols }); if (showModal && should_show_loading && !this.root_store.client.is_logging_in) { this.root_store.ui.toggleUrlUnavailableModal(true); @@ -1282,6 +1286,16 @@ export default class TradeStore extends BaseStore { } } + get is_dtrader_v2_enabled() { + const is_dtrader_v2 = JSON.parse(localStorage.getItem('FeatureFlagsStore') ?? '{}')?.data?.dtrader_v2; + + return ( + is_dtrader_v2 && + this.root_store.ui.is_mobile && + (window.location.pathname.startsWith(routes.trade) || window.location.pathname.startsWith('/contract/')) + ); + } + get is_synthetics_available() { return !!this.active_symbols?.find(item => item.market === 'synthetic_index'); } @@ -1805,6 +1819,7 @@ export default class TradeStore extends BaseStore { }); } if ('active_symbols' in req) { + if (this.is_dtrader_v2_enabled) return; if (this.root_store.client.is_logged_in) { return WS.authorized.activeSymbols('brief'); }