diff --git a/src/contexts/ChartContext.tsx b/src/contexts/ChartContext.tsx index 4bdd710c4c..f5a58a656f 100644 --- a/src/contexts/ChartContext.tsx +++ b/src/contexts/ChartContext.tsx @@ -25,7 +25,11 @@ import { } from '../pages/platformAmbient/Chart/ChartUtils/useUndoRedo'; import { TradeDataContext, TradeDataContextIF } from './TradeDataContext'; import { BrandContext } from './BrandContext'; -import { drawDataHistory, selectedDrawnData, getCssVariable } from '../pages/platformAmbient/Chart/ChartUtils/chartUtils'; +import { + drawDataHistory, + selectedDrawnData, + getCssVariable, +} from '../pages/platformAmbient/Chart/ChartUtils/chartUtils'; type TradeTableState = 'Expanded' | 'Collapsed' | undefined; @@ -52,8 +56,14 @@ export interface ChartContextIF { isChangeScaleChart: boolean; setIsChangeScaleChart: React.Dispatch; isCandleDataNull: boolean; - setNumCandlesFetched: React.Dispatch<{candleCount:number | undefined,switchPeriodFlag:boolean} >; - numCandlesFetched: {candleCount:number | undefined,switchPeriodFlag:boolean}; + setNumCandlesFetched: React.Dispatch<{ + candleCount: number | undefined; + switchPeriodFlag: boolean; + }>; + numCandlesFetched: { + candleCount: number | undefined; + switchPeriodFlag: boolean; + }; setIsCandleDataNull: Dispatch>; isToolbarOpen: boolean; setIsToolbarOpen: React.Dispatch>; @@ -95,11 +105,9 @@ export interface ChartContextIF { SetStateAction >; chartThemeColors: ChartThemeIF | undefined; + setColorChangeTrigger: React.Dispatch>; + colorChangeTrigger: boolean; defaultChartSettings: LocalChartSettingsIF; - localChartSettings: LocalChartSettingsIF | undefined; - setLocalChartSettings: React.Dispatch< - SetStateAction - >; setContextmenu: React.Dispatch>; contextmenu: boolean; setShouldResetBuffer: React.Dispatch>; @@ -257,6 +265,8 @@ export const ChartContextProvider = (props: { children: React.ReactNode }) => { ChartThemeIF | undefined >(undefined); + const [colorChangeTrigger, setColorChangeTrigger] = useState(false); + const [defaultChartSettings] = useState({ chartColors: { upCandleBodyColor: '--accent5', @@ -275,23 +285,6 @@ export const ChartContextProvider = (props: { children: React.ReactNode }) => { showFeeRate: false, }); - const [localChartSettings, setLocalChartSettings] = useState< - LocalChartSettingsIF | undefined - >(undefined); - - useEffect(() => { - if ( - CHART_CONTEXT_SETTINGS_LOCAL_STORAGE && - localChartSettings === undefined - ) { - const parsedContextData = JSON.parse( - CHART_CONTEXT_SETTINGS_LOCAL_STORAGE, - ) as LocalChartSettingsIF; - - setLocalChartSettings(parsedContextData); - } - }, [CHART_CONTEXT_SETTINGS_LOCAL_STORAGE]); - // the max size is based on the max height, and is subtracting the minimum size of table and the padding around the drag bar useEffect(() => { const updateDimension = () => { @@ -351,9 +344,10 @@ export const ChartContextProvider = (props: { children: React.ReactNode }) => { const [isToolbarOpen, setIsToolbarOpen] = useState(initialIsToolbarOpen); - const [numCandlesFetched, setNumCandlesFetched] = useState< - {candleCount: number | undefined, switchPeriodFlag:boolean} - >({candleCount:undefined,switchPeriodFlag:true}); + const [numCandlesFetched, setNumCandlesFetched] = useState<{ + candleCount: number | undefined; + switchPeriodFlag: boolean; + }>({ candleCount: undefined, switchPeriodFlag: true }); const currentPoolString = undoRedoOptions.currentPool.tokenA.address + @@ -399,9 +393,9 @@ export const ChartContextProvider = (props: { children: React.ReactNode }) => { setNumCandlesFetched, chartThemeColors, setChartThemeColors, + colorChangeTrigger, + setColorChangeTrigger, defaultChartSettings, - localChartSettings, - setLocalChartSettings, contextmenu, setContextmenu, contextMenuPlacement, diff --git a/src/pages/Chart/ChartSettings/ChartSettings.tsx b/src/pages/Chart/ChartSettings/ChartSettings.tsx index d9cfe6f338..6ed342993c 100644 --- a/src/pages/Chart/ChartSettings/ChartSettings.tsx +++ b/src/pages/Chart/ChartSettings/ChartSettings.tsx @@ -1,65 +1,27 @@ -import { MouseEvent, useContext, useEffect, useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import * as d3 from 'd3'; import { - ActionButtonContainer, ChartSettingsContainer, - CheckList, - CheckListContainer, CloseButton, - ColorList, - ColorOptions, - ColorPickerContainer, ContextMenu, - ContextMenuContextText, - ContextMenuFooter, ContextMenuHeader, ContextMenuHeaderText, - FooterButtons, - FooterContextText, - Icon, - OptionColor, - SelectionContainer, - StyledCheckbox, - StyledSelectbox, } from './ChartSettingsCss'; import { VscClose } from 'react-icons/vsc'; -import { - ChartThemeIF, - LocalChartSettingsIF, -} from '../../../contexts/ChartContext'; +import { ChartThemeIF } from '../../../contexts/ChartContext'; -import { SketchPicker } from 'react-color'; -import { PoolContext } from '../../../contexts/PoolContext'; import { BrandContext } from '../../../contexts/BrandContext'; -import Spinner from '../../../components/Global/Spinner/Spinner'; -import { TradeDataContext } from '../../../contexts/TradeDataContext'; -import { LS_KEY_CHART_CONTEXT_SETTINGS } from '../../platformAmbient/Chart/ChartUtils/chartConstants'; -import { - chartItemStates, - getCssVariable, -} from '../../platformAmbient/Chart/ChartUtils/chartUtils'; -import { - ColorPickerTab, - DropDownList, - DropDownListContainer, - LabelSettingsArrow, - ListItem, -} from '../../platformAmbient/Chart/Draw/FloatingToolbar/FloatingToolbarSettingsCss'; +import { chartItemStates } from '../../platformAmbient/Chart/ChartUtils/chartUtils'; +import ChartSettingsContent from './ChartSettingsContent'; interface ContextMenuIF { - contextMenuPlacement: { top: number; left: number; isReversed: boolean }; + contextMenuPlacement?: { top: number; left: number; isReversed: boolean }; setContextmenu: React.Dispatch>; - setColorChangeTrigger: React.Dispatch>; chartItemStates: chartItemStates; chartThemeColors: ChartThemeIF; setChartThemeColors: React.Dispatch< React.SetStateAction >; - defaultChartSettings: LocalChartSettingsIF; - localChartSettings: LocalChartSettingsIF | undefined; - setLocalChartSettings: React.Dispatch< - React.SetStateAction - >; isCondensedModeEnabled: boolean; closeOutherChartSetting: boolean; setIsCondensedModeEnabled: React.Dispatch>; @@ -70,7 +32,7 @@ interface ContextMenuIF { render: () => void; } -interface ColorObjIF { +export interface ColorObjIF { selectedColor: string | undefined; // eslint-disable-next-line @typescript-eslint/no-explicit-any replaceSelector: string; @@ -84,10 +46,7 @@ export default function ChartSettings(props: ContextMenuIF) { setContextmenu, chartThemeColors, // setChartThemeColors, - defaultChartSettings, - setLocalChartSettings, - render, - setColorChangeTrigger, + // render, isCondensedModeEnabled, setIsCondensedModeEnabled, setShouldDisableChartSettings, @@ -95,32 +54,14 @@ export default function ChartSettings(props: ContextMenuIF) { setCloseOutherChartSetting, } = props; - const { - showFeeRate, - setShowFeeRate, - showTvl, - setShowTvl, - showVolume, - setShowVolume, - } = props.chartItemStates; - const contextMenuRef = useRef(null); - const { isTradeDollarizationEnabled, setIsTradeDollarizationEnabled } = - useContext(PoolContext); - - const { skin, platformName } = useContext(BrandContext); + const { platformName } = useContext(BrandContext); const [isSaving, setIsSaving] = useState(false); const [applyDefault, setApplyDefault] = useState(false); const [reverseColorObj, setReverseColorObj] = useState(false); - const { - baseToken: { symbol: baseTokenSymbol }, - quoteToken: { symbol: quoteTokenSymbol }, - isDenomBase, - } = useContext(TradeDataContext); - useEffect(() => { d3.select(contextMenuRef.current).on( 'contextmenu', @@ -133,12 +74,14 @@ export default function ChartSettings(props: ContextMenuIF) { useEffect(() => { const screenHeight = window.innerHeight; - const diff = screenHeight - contextMenuPlacement.top; + if (contextMenuPlacement) { + const diff = screenHeight - contextMenuPlacement.top; - setReverseColorObj( - (contextMenuPlacement.isReversed && diff < 260) || - (!contextMenuPlacement.isReversed && diff < 700), - ); + setReverseColorObj( + (contextMenuPlacement.isReversed && diff < 260) || + (!contextMenuPlacement.isReversed && diff < 700), + ); + } }, [contextMenuPlacement]); useEffect(() => { @@ -149,284 +92,20 @@ export default function ChartSettings(props: ContextMenuIF) { } }, [closeOutherChartSetting]); - const handleCandleColorPicker = ( - replaceSelector: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - newColor: any, - ) => { - const colorRgbaCode = - 'rgba(' + - newColor.rgb.r + - ',' + - newColor.rgb.g + - ',' + - newColor.rgb.b + - ',' + - newColor.rgb.a + - ')'; - - const replaceColor = d3.color(colorRgbaCode); - - if (replaceSelector && replaceColor) { - chartThemeColors[replaceSelector] = replaceColor; - - setColorChangeTrigger(true); - - setSelectedColorObj((prev: ColorObjIF | undefined) => { - if (prev) { - const colorRep = { - selectedColor: replaceColor.toString(), - replaceSelector: prev.replaceSelector, - index: prev.index, - placement: prev.placement, - } as ColorObjIF; - - return colorRep; - } - }); - - render(); - } - }; - - const handleApplyDefaults = ( - chartSettings: LocalChartSettingsIF, - isDefault = true, - ) => { - setApplyDefault(true); - - setShowVolume(chartSettings.showVolume); - setShowTvl(chartSettings.showTvl); - setShowFeeRate(chartSettings.showFeeRate); - - setColorChangeTrigger(true); - - setIsTradeDollarizationEnabled( - chartSettings.isTradeDollarizationEnabled, - ); - - const upCandleBodyColor = isDefault - ? getCssVariable(skin.active, chartSettings.chartColors.upCandleBodyColor) - : d3.color(chartSettings.chartColors.upCandleBodyColor); - - const downCandleBodyColor = isDefault - ? getCssVariable( - skin.active, - chartSettings.chartColors.downCandleBodyColor, - ) - : d3.color(chartSettings.chartColors.downCandleBodyColor); - - const selectedDateFillColor = isDefault - ? getCssVariable( - skin.active, - chartSettings.chartColors.selectedDateFillColor, - ) - : d3.color(chartSettings.chartColors.selectedDateFillColor); - - const downCandleBorderColor = isDefault - ? getCssVariable( - skin.active, - chartSettings.chartColors.downCandleBorderColor, - ) - : d3.color(chartSettings.chartColors.downCandleBorderColor); - - const upCandleBorderColor = isDefault - ? getCssVariable( - skin.active, - chartSettings.chartColors.upCandleBorderColor, - ) - : d3.color(chartSettings.chartColors.upCandleBorderColor); - - const liqAskColor = isDefault - ? getCssVariable(skin.active, chartSettings.chartColors.liqAskColor) - : d3.color(chartSettings.chartColors.liqAskColor); - - const liqBidColor = isDefault - ? getCssVariable(skin.active, chartSettings.chartColors.liqBidColor) - : d3.color(chartSettings.chartColors.liqBidColor); - - const selectedDateStrokeColor = isDefault - ? getCssVariable( - skin.active, - chartSettings.chartColors.selectedDateStrokeColor, - ) - : d3.color(chartSettings.chartColors.selectedDateStrokeColor); - - chartThemeColors.upCandleBodyColor = upCandleBodyColor; - chartThemeColors.downCandleBodyColor = downCandleBodyColor; - chartThemeColors.selectedDateFillColor = selectedDateFillColor; - chartThemeColors.upCandleBorderColor = upCandleBorderColor; - chartThemeColors.downCandleBorderColor = downCandleBorderColor; - chartThemeColors.liqAskColor = liqAskColor; - chartThemeColors.liqBidColor = liqBidColor; - chartThemeColors.selectedDateStrokeColor = selectedDateStrokeColor; - - const applyTimeOut = setTimeout(() => { - setApplyDefault(false); - }, 1000); - return () => { - clearTimeout(applyTimeOut); - }; - }; - - const handleCancelChanges = () => { - const CHART_CONTEXT_SETTINGS_LOCAL_STORAGE = localStorage.getItem( - LS_KEY_CHART_CONTEXT_SETTINGS, - ); - - if (CHART_CONTEXT_SETTINGS_LOCAL_STORAGE) { - const parsedContextData = JSON.parse( - CHART_CONTEXT_SETTINGS_LOCAL_STORAGE, - ) as LocalChartSettingsIF; - handleApplyDefaults(parsedContextData, false); - } else { - handleApplyDefaults(defaultChartSettings); - } - - setColorChangeTrigger(true); - setContextmenu(false); - }; - - const handleSaveChanges = () => { - setIsSaving(true); - const localSettings = { - chartColors: { - upCandleBodyColor: chartThemeColors.upCandleBodyColor - ? chartThemeColors.upCandleBodyColor.toString() - : '--accent5', - downCandleBodyColor: chartThemeColors.downCandleBodyColor - ? chartThemeColors.downCandleBodyColor.toString() - : '--dark2', - selectedDateFillColor: chartThemeColors.selectedDateFillColor - ? chartThemeColors.selectedDateFillColor.toString() - : '--accent2', - upCandleBorderColor: chartThemeColors.upCandleBorderColor - ? chartThemeColors.upCandleBorderColor.toString() - : '--accent5', - downCandleBorderColor: chartThemeColors.downCandleBorderColor - ? chartThemeColors.downCandleBorderColor.toString() - : '--accent1', - liqAskColor: chartThemeColors.liqAskColor - ? chartThemeColors.liqAskColor.toString() - : '--accent5', - liqBidColor: chartThemeColors.liqBidColor - ? chartThemeColors.liqBidColor.toString() - : '--accent1', - selectedDateStrokeColor: - chartThemeColors.selectedDateStrokeColor - ? chartThemeColors.selectedDateStrokeColor.toString() - : '--accent2', - textColor: chartThemeColors.textColor - ? chartThemeColors.textColor.toString() - : '', - }, - isTradeDollarizationEnabled: isTradeDollarizationEnabled, - showVolume: showVolume, - showTvl: showTvl, - showFeeRate: showFeeRate, - }; - - setLocalChartSettings(localSettings); - - localStorage.setItem( - LS_KEY_CHART_CONTEXT_SETTINGS, - JSON.stringify(localSettings), - ); - - const savedTimeOut = setTimeout(() => { - setIsSaving(false); - setContextmenu(false); - }, 1000); - return () => { - clearTimeout(savedTimeOut); - }; - }; - - const handlePriceInChange = (option: string) => { - setIsTradeDollarizationEnabled( - option !== quoteTokenSymbol && option !== baseTokenSymbol, - ); - setPriceInOption(option); - }; - const [selectedColorObj, setSelectedColorObj] = useState< ColorObjIF | undefined >(undefined); const [isSelecboxActive, setIsSelecboxActive] = useState(false); - const [priceInOption, setPriceInOption] = useState( - !isTradeDollarizationEnabled - ? isDenomBase - ? quoteTokenSymbol - : baseTokenSymbol - : 'USD', - ); - - const checkListContent = [ - { - checked: showVolume, - action: setShowVolume, - selection: 'Show Volume', - }, - { - checked: showTvl, - action: setShowTvl, - selection: 'Show TVL', - }, - { - checked: showFeeRate, - action: setShowFeeRate, - selection: 'Show Fee Rate', - }, - { - checked: isCondensedModeEnabled, - action: setIsCondensedModeEnabled, - selection: 'Hide empty candles', - }, - ]; - - const selectionContent = [ - { - selection: 'Show prices in', - action: handlePriceInChange, - options: [isDenomBase ? quoteTokenSymbol : baseTokenSymbol, 'USD'], - }, - ]; - - const colorPickerContent = [ - { - selection: 'Candle Body', - actionHandler: 'body', - action: handleCandleColorPicker, - upColor: 'upCandleBodyColor', - downColor: 'downCandleBodyColor', - exclude: [''], - }, - { - selection: 'Candle Borders', - actionHandler: 'border', - action: handleCandleColorPicker, - upColor: 'upCandleBorderColor', - downColor: 'downCandleBorderColor', - exclude: [''], - }, - { - selection: 'Liquidity Area', - actionHandler: 'liq', - action: handleCandleColorPicker, - upColor: 'liqAskColor', - downColor: 'liqBidColor', - exclude: ['futa'], - }, - ]; - return ( { setShouldDisableChartSettings(true); setSelectedColorObj(undefined); @@ -445,366 +124,26 @@ export default function ChartSettings(props: ContextMenuIF) { - - {checkListContent.map((item, index) => ( - - item.action(!item.checked)} - > - - - - - - {['futa'].includes(platformName) - ? item.selection.toUpperCase() - : item.selection} - - - ))} - - - - {selectionContent.map((item, index) => ( - - - {['futa'].includes(platformName) - ? item.selection.toUpperCase() - : item.selection} - - ) => { - event.stopPropagation(); - setIsSelecboxActive(!isSelecboxActive); - }} - > - - {priceInOption} - - - - - {isSelecboxActive && ( -
- - - {item.options.map( - (option, index) => ( - , - ) => { - event.stopPropagation(); - item.action(option); - }} - > - {option} - - ), - )} - - -
- )} -
- ))} -
- - - {colorPickerContent.map( - (item, index) => - !item.exclude.includes(platformName) && ( - - - {['futa'].includes(platformName) - ? item.selection.toUpperCase() - : item.selection} - - - - , - ) => { - event.stopPropagation(); - setSelectedColorObj((prev) => { - const selectedObj = { - selectedColor: - chartThemeColors[ - item.upColor - ]?.toString(), - replaceSelector: - item.upColor, - index: index, - placement: 'left', - }; - - const result = - prev === undefined || - prev.index !== index || - prev.placement !== - 'left' - ? selectedObj - : undefined; - - setShouldDisableChartSettings( - result === undefined, - ); - - return result; - }); - }} - > - {item.downColor !== '' && ( - , - ) => { - event.stopPropagation(); - setSelectedColorObj( - (prev) => { - const selectedObj = - { - selectedColor: - chartThemeColors[ - item - .downColor - ]?.toString(), - replaceSelector: - item.downColor, - index: index, - placement: - 'right', - }; - - const result = - prev === - undefined || - prev.index !== - index || - prev.placement !== - 'right' - ? selectedObj - : undefined; - - setShouldDisableChartSettings( - result === - undefined, - ); - - return result; - }, - ); - }} - > - )} - - {selectedColorObj && - selectedColorObj.index === - index && ( - , - ) => - event.stopPropagation() - } - > - { - event.stopPropagation(); - item.action( - selectedColorObj.replaceSelector, - color, - ); - }} - /> - - )} - - - ), - )} - - - - - handleApplyDefaults(defaultChartSettings) - } - isFuta={['futa'].includes(platformName)} - > - {applyDefault ? ( - - ) : ( - - {['futa'].includes(platformName) - ? 'DEFAULTS' - : 'Apply defaults'} - - )} - - -
- handleCancelChanges()} - isFuta={['futa'].includes(platformName)} - > - - {['futa'].includes(platformName) - ? 'APPLY' - : 'Cancel'} - - -
-
- handleSaveChanges()} - isFuta={['futa'].includes(platformName)} - > - {isSaving ? ( - - ) : ( - - {['futa'].includes(platformName) - ? 'OK' - : 'Save'} - - )} - -
-
-
+
); diff --git a/src/pages/Chart/ChartSettings/ChartSettingsContent.tsx b/src/pages/Chart/ChartSettings/ChartSettingsContent.tsx new file mode 100644 index 0000000000..1c039bf447 --- /dev/null +++ b/src/pages/Chart/ChartSettings/ChartSettingsContent.tsx @@ -0,0 +1,774 @@ +import * as d3 from 'd3'; +import { SketchPicker } from 'react-color'; +import { ColorPickerTab } from '../../platformAmbient/Chart/Draw/FloatingToolbar/FloatingToolbarCss'; +import { + LabelSettingsArrow, + DropDownListContainer, + DropDownList, + ListItem, +} from '../../platformAmbient/Chart/Draw/FloatingToolbar/FloatingToolbarSettingsCss'; +import { + ActionButtonContainer, + CheckList, + CheckListContainer, + ColorList, + ColorOptions, + ColorPickerContainer, + ContextMenuContextText, + ContextMenuFooter, + FooterButtons, + FooterContextText, + Icon, + OptionColor, + SelectionContainer, + StyledCheckbox, + StyledSelectbox, +} from './ChartSettingsCss'; +import { + ChartContext, + ChartThemeIF, + LocalChartSettingsIF, +} from '../../../contexts/ChartContext'; +import { + chartItemStates, + getCssVariable, +} from '../../platformAmbient/Chart/ChartUtils/chartUtils'; +import { MouseEvent, useContext, useEffect, useMemo, useState } from 'react'; +import { PoolContext } from '../../../contexts/PoolContext'; +import { TradeDataContext } from '../../../contexts/TradeDataContext'; +import { ColorObjIF } from './ChartSettings'; +import { BrandContext } from '../../../contexts/BrandContext'; +import Spinner from '../../../components/Global/Spinner/Spinner'; +import { LS_KEY_CHART_CONTEXT_SETTINGS } from '../../platformAmbient/Chart/ChartUtils/chartConstants'; + +interface ContextMenuContentIF { + chartThemeColors: ChartThemeIF; + isCondensedModeEnabled: boolean; + setIsCondensedModeEnabled: React.Dispatch>; + setShouldDisableChartSettings: React.Dispatch< + React.SetStateAction + >; + chartItemStates: chartItemStates; + isSelecboxActive: boolean; + setIsSelecboxActive: React.Dispatch>; + selectedColorObj: ColorObjIF | undefined; + setSelectedColorObj: React.Dispatch< + React.SetStateAction + >; + reverseColorObj: boolean; + applyDefault: boolean; + setApplyDefault: React.Dispatch>; + isSaving: boolean; + setIsSaving: React.Dispatch>; + isMobile: boolean; + // render: () => void; +} + +export default function ChartSettingsContent(props: ContextMenuContentIF) { + const { + chartThemeColors, + isCondensedModeEnabled, + setIsCondensedModeEnabled, + setShouldDisableChartSettings, + isSelecboxActive, + setIsSelecboxActive, + selectedColorObj, + setSelectedColorObj, + reverseColorObj, + applyDefault, + setApplyDefault, + isSaving, + setIsSaving, + isMobile, + // render, + } = props; + + const { + showFeeRate, + setShowFeeRate, + showTvl, + setShowTvl, + showVolume, + setShowVolume, + } = props.chartItemStates; + + const { isTradeDollarizationEnabled, setIsTradeDollarizationEnabled } = + useContext(PoolContext); + + const { skin, platformName } = useContext(BrandContext); + const { defaultChartSettings, setColorChangeTrigger, setContextmenu } = + useContext(ChartContext); + + const { + baseToken: { symbol: baseTokenSymbol }, + quoteToken: { symbol: quoteTokenSymbol }, + isDenomBase, + } = useContext(TradeDataContext); + + const [priceInOption, setPriceInOption] = useState( + !isTradeDollarizationEnabled + ? isDenomBase + ? quoteTokenSymbol + : baseTokenSymbol + : 'USD', + ); + + const handlePriceInChange = (option: string) => { + setIsTradeDollarizationEnabled( + option !== quoteTokenSymbol && option !== baseTokenSymbol, + ); + setPriceInOption(option); + }; + + const handleCandleColorPicker = ( + replaceSelector: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + newColor: any, + ) => { + const colorRgbaCode = + 'rgba(' + + newColor.rgb.r + + ',' + + newColor.rgb.g + + ',' + + newColor.rgb.b + + ',' + + newColor.rgb.a + + ')'; + + const replaceColor = d3.color(colorRgbaCode); + + if (replaceSelector && replaceColor) { + chartThemeColors[replaceSelector] = replaceColor; + + setColorChangeTrigger(true); + + setSelectedColorObj((prev: ColorObjIF | undefined) => { + if (prev) { + const colorRep = { + selectedColor: replaceColor.toString(), + replaceSelector: prev.replaceSelector, + index: prev.index, + placement: prev.placement, + } as ColorObjIF; + + return colorRep; + } + }); + + // render(); + } + }; + + const memoizedChartSettings = useMemo(() => { + if (isSaving) { + console.log('isSaving'); + const localSettings = { + chartColors: { + upCandleBodyColor: chartThemeColors.upCandleBodyColor + ? chartThemeColors.upCandleBodyColor.toString() + : '--accent5', + downCandleBodyColor: chartThemeColors.downCandleBodyColor + ? chartThemeColors.downCandleBodyColor.toString() + : '--dark2', + selectedDateFillColor: + chartThemeColors.selectedDateFillColor + ? chartThemeColors.selectedDateFillColor.toString() + : '--accent2', + upCandleBorderColor: chartThemeColors.upCandleBorderColor + ? chartThemeColors.upCandleBorderColor.toString() + : '--accent5', + downCandleBorderColor: + chartThemeColors.downCandleBorderColor + ? chartThemeColors.downCandleBorderColor.toString() + : '--accent1', + liqAskColor: chartThemeColors.liqAskColor + ? chartThemeColors.liqAskColor.toString() + : '--accent5', + liqBidColor: chartThemeColors.liqBidColor + ? chartThemeColors.liqBidColor.toString() + : '--accent1', + selectedDateStrokeColor: + chartThemeColors.selectedDateStrokeColor + ? chartThemeColors.selectedDateStrokeColor.toString() + : '--accent2', + textColor: chartThemeColors.textColor + ? chartThemeColors.textColor.toString() + : '', + }, + isTradeDollarizationEnabled: isTradeDollarizationEnabled, + showVolume: showVolume, + showTvl: showTvl, + showFeeRate: showFeeRate, + }; + + // Saves to local storage + localStorage.setItem( + LS_KEY_CHART_CONTEXT_SETTINGS, + JSON.stringify(localSettings), + ); + + return localSettings; + } else { + console.log('else'); + const CHART_CONTEXT_SETTINGS_LOCAL_STORAGE = localStorage.getItem( + LS_KEY_CHART_CONTEXT_SETTINGS, + ); + + if (CHART_CONTEXT_SETTINGS_LOCAL_STORAGE) { + const parsedContextData = JSON.parse( + CHART_CONTEXT_SETTINGS_LOCAL_STORAGE, + ) as LocalChartSettingsIF; + return parsedContextData; + } else { + return defaultChartSettings; + } + } + }, [isSaving]); + + useEffect(() => { + if (applyDefault) { + handleApplyChartThemeChanges(defaultChartSettings); + } + }, [applyDefault]); + + const handleApplyChartThemeChanges = ( + chartSettings: LocalChartSettingsIF, + isDefault = true, + ) => { + setApplyDefault(true); + + setShowVolume(chartSettings.showVolume); + setShowTvl(chartSettings.showTvl); + setShowFeeRate(chartSettings.showFeeRate); + + setColorChangeTrigger(true); + + setIsTradeDollarizationEnabled( + chartSettings.isTradeDollarizationEnabled, + ); + + const upCandleBodyColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.upCandleBodyColor, + ) + : d3.color(chartSettings.chartColors.upCandleBodyColor); + + const downCandleBodyColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.downCandleBodyColor, + ) + : d3.color(chartSettings.chartColors.downCandleBodyColor); + + const selectedDateFillColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.selectedDateFillColor, + ) + : d3.color(chartSettings.chartColors.selectedDateFillColor); + + const downCandleBorderColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.downCandleBorderColor, + ) + : d3.color(chartSettings.chartColors.downCandleBorderColor); + + const upCandleBorderColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.upCandleBorderColor, + ) + : d3.color(chartSettings.chartColors.upCandleBorderColor); + + const liqAskColor = isDefault + ? getCssVariable(skin.active, chartSettings.chartColors.liqAskColor) + : d3.color(chartSettings.chartColors.liqAskColor); + + const liqBidColor = isDefault + ? getCssVariable(skin.active, chartSettings.chartColors.liqBidColor) + : d3.color(chartSettings.chartColors.liqBidColor); + + const selectedDateStrokeColor = isDefault + ? getCssVariable( + skin.active, + chartSettings.chartColors.selectedDateStrokeColor, + ) + : d3.color(chartSettings.chartColors.selectedDateStrokeColor); + + chartThemeColors.upCandleBodyColor = upCandleBodyColor; + chartThemeColors.downCandleBodyColor = downCandleBodyColor; + chartThemeColors.selectedDateFillColor = selectedDateFillColor; + chartThemeColors.upCandleBorderColor = upCandleBorderColor; + chartThemeColors.downCandleBorderColor = downCandleBorderColor; + chartThemeColors.liqAskColor = liqAskColor; + chartThemeColors.liqBidColor = liqBidColor; + chartThemeColors.selectedDateStrokeColor = selectedDateStrokeColor; + + const applyTimeOut = setTimeout(() => { + setApplyDefault(false); + }, 1000); + return () => { + clearTimeout(applyTimeOut); + }; + }; + + const handleCancelChanges = () => { + if (memoizedChartSettings) { + handleApplyChartThemeChanges(memoizedChartSettings, false); + } else { + handleApplyChartThemeChanges(defaultChartSettings); + } + + setColorChangeTrigger(true); + setContextmenu(false); + }; + + const handleSaveChanges = () => { + setIsSaving(true); + + const savedTimeOut = setTimeout(() => { + setIsSaving(false); + setContextmenu(false); + }, 1000); + return () => { + clearTimeout(savedTimeOut); + }; + }; + + const checkListContent = [ + { + checked: showVolume, + action: setShowVolume, + selection: 'Show Volume', + }, + { + checked: showTvl, + action: setShowTvl, + selection: 'Show TVL', + }, + { + checked: showFeeRate, + action: setShowFeeRate, + selection: 'Show Fee Rate', + }, + { + checked: isCondensedModeEnabled, + action: setIsCondensedModeEnabled, + selection: 'Hide empty candles', + }, + ]; + + const selectionContent = [ + { + selection: 'Show prices in', + action: handlePriceInChange, + options: [isDenomBase ? quoteTokenSymbol : baseTokenSymbol, 'USD'], + }, + ]; + + const colorPickerContent = [ + { + selection: 'Candle Body', + actionHandler: 'body', + action: handleCandleColorPicker, + upColor: 'upCandleBodyColor', + downColor: 'downCandleBodyColor', + exclude: [''], + }, + { + selection: 'Candle Borders', + actionHandler: 'border', + action: handleCandleColorPicker, + upColor: 'upCandleBorderColor', + downColor: 'downCandleBorderColor', + exclude: [''], + }, + { + selection: 'Liquidity Area', + actionHandler: 'liq', + action: handleCandleColorPicker, + upColor: 'liqAskColor', + downColor: 'liqBidColor', + exclude: ['futa'], + }, + ]; + + return ( + <> + <> + + {checkListContent.map((item, index) => ( + + item.action(!item.checked)} + > + + + + + + {['futa'].includes(platformName) + ? item.selection.toUpperCase() + : item.selection} + + + ))} + + + + {selectionContent.map((item, index) => ( + + + {['futa'].includes(platformName) + ? item.selection.toUpperCase() + : item.selection} + + ) => { + event.stopPropagation(); + setIsSelecboxActive(!isSelecboxActive); + }} + > + + {priceInOption} + + + + {isSelecboxActive && ( +
+ + + {item.options.map( + (option, index) => ( + , + ) => { + event.stopPropagation(); + item.action( + option, + ); + }} + > + {option} + + ), + )} + + +
+ )} +
+
+ ))} +
+ + + {colorPickerContent.map( + (item, index) => + !item.exclude.includes(platformName) && ( + + + {['futa'].includes(platformName) + ? item.selection.toUpperCase() + : item.selection} + + + + , + ) => { + event.stopPropagation(); + setSelectedColorObj((prev) => { + const selectedObj = { + selectedColor: + chartThemeColors[ + item.upColor + ]?.toString(), + replaceSelector: + item.upColor, + index: index, + placement: 'left', + }; + + const result = + prev === undefined || + prev.index !== index || + prev.placement !== + 'left' + ? selectedObj + : undefined; + + setShouldDisableChartSettings( + result === undefined, + ); + + return result; + }); + }} + > + {item.downColor !== '' && ( + , + ) => { + event.stopPropagation(); + setSelectedColorObj( + (prev) => { + const selectedObj = + { + selectedColor: + chartThemeColors[ + item + .downColor + ]?.toString(), + replaceSelector: + item.downColor, + index: index, + placement: + 'right', + }; + + const result = + prev === + undefined || + prev.index !== + index || + prev.placement !== + 'right' + ? selectedObj + : undefined; + + setShouldDisableChartSettings( + result === + undefined, + ); + + return result; + }, + ); + }} + > + )} + + {selectedColorObj && + selectedColorObj.index === + index && ( + , + ) => + event.stopPropagation() + } + > + { + event.stopPropagation(); + item.action( + selectedColorObj.replaceSelector, + color, + ); + }} + /> + + )} + + + ), + )} + + + + {!isMobile && ( + + + handleApplyChartThemeChanges(defaultChartSettings) + } + isFuta={['futa'].includes(platformName)} + > + {applyDefault ? ( + + ) : ( + + {['futa'].includes(platformName) + ? 'DEFAULTS' + : 'Apply defaults'} + + )} + + +
+ handleCancelChanges()} + isFuta={['futa'].includes(platformName)} + > + + {['futa'].includes(platformName) + ? 'APPLY' + : 'Cancel'} + + +
+ +
+ handleSaveChanges()} + isFuta={['futa'].includes(platformName)} + > + {isSaving ? ( + + ) : ( + + {['futa'].includes(platformName) + ? 'OK' + : 'Save'} + + )} + +
+
+
+ )} + + ); +} diff --git a/src/pages/Chart/ChartSettings/ChartSettingsCss.ts b/src/pages/Chart/ChartSettings/ChartSettingsCss.ts index 5a68c3e256..5434d2ac0b 100644 --- a/src/pages/Chart/ChartSettings/ChartSettingsCss.ts +++ b/src/pages/Chart/ChartSettings/ChartSettingsCss.ts @@ -69,6 +69,7 @@ const ContextMenuContextText = styled.div` font-family: Lexend Deca; font-size: 12px; font-weight: 300; + line-height: 15px; letter-spacing: -0.02em; text-align: left; @@ -93,6 +94,8 @@ const CheckListContainer = styled.div` `; const CheckList = styled.div` + position: relative; + display: flex; flex-direction: row; @@ -248,8 +251,6 @@ const StyledSelectbox = styled.div` cursor: pointer; - padding: 4px; - border-radius: 4px; border: 1px solid var(--text3); diff --git a/src/pages/platformAmbient/Chart/Chart.tsx b/src/pages/platformAmbient/Chart/Chart.tsx index dadd6e633e..9cf331673b 100644 --- a/src/pages/platformAmbient/Chart/Chart.tsx +++ b/src/pages/platformAmbient/Chart/Chart.tsx @@ -176,6 +176,7 @@ interface propsIF { chartResetStatus: { isResetChart: boolean; }; + openMobileSettingsModal: () => void; } export default function Chart(props: propsIF) { @@ -207,6 +208,7 @@ export default function Chart(props: propsIF) { setIsCompletedFetchData, setChartResetStatus, chartResetStatus, + openMobileSettingsModal, } = props; const { @@ -236,15 +238,14 @@ export default function Chart(props: propsIF) { setChartContainerOptions, chartThemeColors, setChartThemeColors, - defaultChartSettings, - localChartSettings, - setLocalChartSettings, contextmenu, setContextmenu, contextMenuPlacement, setContextMenuPlacement, shouldResetBuffer, setShouldResetBuffer, + colorChangeTrigger, + setColorChangeTrigger, } = useContext(ChartContext); const chainId = chainData.chainId; @@ -317,8 +318,6 @@ export default function Chart(props: propsIF) { const [handleDocumentEvent, setHandleDocumentEvent] = useState(); const period = unparsedData.duration; - const [colorChangeTrigger, setColorChangeTrigger] = useState(false); - const side = (isDenomBase && !isBid) || (!isDenomBase && isBid) ? 'buy' : 'sell'; const sellOrderStyle = side === 'sell' ? 'order_sell' : 'order_buy'; @@ -1443,21 +1442,7 @@ export default function Chart(props: propsIF) { startTouch.clientY === event.sourceEvent.changedTouches[0].clientY ) { - const canvas = d3 - .select(d3CanvasMain.current) - .select('canvas') - .node() as HTMLCanvasElement; - - const rectCanvas = - canvas.getBoundingClientRect(); - - setContextMenuPlacement({ - top: rectCanvas.top, - left: rectCanvas.left + 10, - isReversed: false, - }); - - setContextmenu(true); + openMobileSettingsModal(); } if ( @@ -4734,22 +4719,27 @@ export default function Chart(props: propsIF) { d3.select(d3CanvasMain.current).on( 'contextmenu', (event: PointerEvent) => { - if (!event.shiftKey) { + if (mobileView) { event.preventDefault(); + openMobileSettingsModal(); + } else { + if (!event.shiftKey) { + event.preventDefault(); - const screenHeight = window.innerHeight; + const screenHeight = window.innerHeight; - const diff = screenHeight - event.clientY; + const diff = screenHeight - event.clientY; - setContextMenuPlacement({ - top: event.clientY, - left: event.clientX, - isReversed: diff < 350, - }); + setContextMenuPlacement({ + top: event.clientY, + left: event.clientX, + isReversed: diff < 350, + }); - setContextmenu(true); - } else { - setContextmenu(false); + setContextmenu(true); + } else { + setContextmenu(false); + } } }, ); @@ -5567,7 +5557,7 @@ export default function Chart(props: propsIF) { const { isHoverCandleOrVolumeData, nearest } = candleOrVolumeDataHoverStatus(offsetX, offsetY); - setCrossHairDataFunc(nearest?.time, offsetX, offsetY); + setCrossHairDataFunc(nearest?.time, offsetX, offsetY); let isOrderHistorySelected = undefined; if ( @@ -6353,11 +6343,7 @@ export default function Chart(props: propsIF) { chartItemStates={props.chartItemStates} chartThemeColors={chartThemeColors} setChartThemeColors={setChartThemeColors} - defaultChartSettings={defaultChartSettings} - localChartSettings={localChartSettings} - setLocalChartSettings={setLocalChartSettings} render={render} - setColorChangeTrigger={setColorChangeTrigger} isCondensedModeEnabled={isCondensedModeEnabled} setIsCondensedModeEnabled={setIsCondensedModeEnabled} setShouldDisableChartSettings={ diff --git a/src/pages/platformAmbient/Trade/TradeCharts/TradeCandleStickChart.tsx b/src/pages/platformAmbient/Trade/TradeCharts/TradeCandleStickChart.tsx index 4ee97216bc..a0f419824a 100644 --- a/src/pages/platformAmbient/Trade/TradeCharts/TradeCandleStickChart.tsx +++ b/src/pages/platformAmbient/Trade/TradeCharts/TradeCandleStickChart.tsx @@ -67,10 +67,11 @@ interface propsIF { showLatest: boolean | undefined; setShowLatest: Dispatch>; updateURL: (changes: updatesIF) => void; + openMobileSettingsModal: () => void; } function TradeCandleStickChart(props: propsIF) { - const { selectedDate, setSelectedDate, updateURL } = props; + const { selectedDate, setSelectedDate, updateURL, openMobileSettingsModal } = props; const { candleData, @@ -1201,6 +1202,8 @@ function TradeCandleStickChart(props: propsIF) { setIsCompletedFetchData={setIsCompletedFetchData} setChartResetStatus={setChartResetStatus} chartResetStatus={chartResetStatus} + openMobileSettingsModal={openMobileSettingsModal} + /> )} diff --git a/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.module.css b/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.module.css index 463e8b048f..3a7aeaedcd 100644 --- a/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.module.css +++ b/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.module.css @@ -54,6 +54,10 @@ } .settings_apply_button_container { width: 100%; + + gap: 15px; + padding: 10px; + display: flex; justify-content: center; align-items: center; diff --git a/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.tsx b/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.tsx index 1b86aa0ab8..11fc2472bf 100644 --- a/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.tsx +++ b/src/pages/platformAmbient/Trade/TradeCharts/TradeCharts.tsx @@ -37,7 +37,10 @@ import TimeFrame from './TradeChartsComponents/TimeFrame'; import VolumeTVLFee from './TradeChartsComponents/VolumeTVLFee'; import Modal from '../../../../components/Global/Modal/Modal'; import DollarizationModalControl from '../../../../components/Global/DollarizationModalControl/DollarizationModalControl'; -import { PoolContext } from '../../../../contexts'; +import { CandleContext, PoolContext } from '../../../../contexts'; +import ChartSettingsContent from '../../../Chart/ChartSettings/ChartSettingsContent'; +import { ColorObjIF } from '../../../Chart/ChartSettings/ChartSettings'; +import Spinner from '../../../../components/Global/Spinner/Spinner'; // interface for React functional component props interface propsIF { changeState: ( @@ -83,6 +86,7 @@ function TradeCharts(props: propsIF) { updateURL, isMobileSettingsModalOpen, closeMobileSettingsModal, + openMobileSettingsModal, } = props; const { isPoolDropdownOpen, setIsPoolDropdownOpen } = @@ -99,8 +103,12 @@ function TradeCharts(props: propsIF) { isFullScreen: isChartFullScreen, setIsFullScreen: setIsChartFullScreen, chartCanvasRef, + chartThemeColors, } = useContext(ChartContext); + const { isCondensedModeEnabled, setIsCondensedModeEnabled } = + useContext(CandleContext); + const { isUserConnected } = useContext(UserDataContext); const { platformName } = useContext(BrandContext); @@ -197,6 +205,54 @@ function TradeCharts(props: propsIF) { } }, [isUserConnected]); + const [shouldDisableChartSettings, setShouldDisableChartSettings] = + useState(true); + + const [selectedColorObj, setSelectedColorObj] = useState< + ColorObjIF | undefined + >(undefined); + + const [isSelecboxActive, setIsSelecboxActive] = useState(false); + + const [applyDefault, setApplyDefault] = useState(false); + const [isSaving, setIsSaving] = useState(false); + + const handleModalOnClose = () => { + if (shouldDisableChartSettings && !isSelecboxActive) { + closeMobileSettingsModal(); + } else { + setShouldDisableChartSettings(true); + setSelectedColorObj(undefined); + setIsSelecboxActive(false); + } + }; + + const handleSaveChanges = () => { + setShouldDisableChartSettings(true); + setSelectedColorObj(undefined); + setIsSelecboxActive(false); + + setIsSaving(true); + + const savedTimeOut = setTimeout(() => { + setIsSaving(false); + closeMobileSettingsModal(); + }, 1000); + return () => { + clearTimeout(savedTimeOut); + }; + }; + + const handleReset = () => { + setApplyDefault(true); + }; + + // const render = useCallback(() => { + // // eslint-disable-next-line @typescript-eslint/no-explicit-any + // const nd = d3.select('#d3fc_group').node() as any; + // if (nd) nd.requestRedraw(); + // }, []); + // END OF CHART SETTINGS------------------------------------------------------------ function closeOnEscapeKeyDown(e: KeyboardEvent) { @@ -327,18 +383,65 @@ function TradeCharts(props: propsIF) { )} ); + + const settingsContent = chartThemeColors && ( +
{ + setShouldDisableChartSettings(true); + setSelectedColorObj(undefined); + setIsSelecboxActive(false); + }} + className={styles.time_frame_container} + > + +
+ ); + const timeFrameContent = smallScreen ? ( <> {isMobileSettingsModalOpen && ( - - {timeFrameContentDesktop} + + {settingsContent}
- + +
@@ -404,6 +507,7 @@ function TradeCharts(props: propsIF) { showLatest={showLatest} setShowLatest={setShowLatest} updateURL={updateURL} + openMobileSettingsModal={openMobileSettingsModal} />