Загрузка данных
import { MoexChart, Timeframes } from 'moex-chart';
// eslint-disable-next-line import/no-unresolved -- MOEX_CHART
import { CompareManager } from 'moex-chart/dist/types/core/CompareManager';
import { useEffect, useRef, useState } from 'react';
import { useChangeProperties, useSelectProperties } from '@modules/widgetProperties';
import { ChartIndicativeData, ChartProps } from '@widgets/Chart/types';
import { MOEX_CHART_CONFIG } from '../constants';
import { dataSourceProvider, DataSourceProvider } from '../dataSourceProvide';
import type { IMoexChart } from 'moex-chart';
type TUseMoexChartProps = {
symbol: string;
indicativeData: ChartIndicativeData | undefined;
};
export const useMoexChart = ({ symbol, indicativeData }: TUseMoexChartProps) => {
const moexChartState = useSelectProperties((wProps: Partial<ChartProps>) => wProps.moexChartState);
const { updateProperties } = useChangeProperties<ChartProps>();
const [isCompareOpen, setIsCompareOpen] = useState(false);
const containerRef = useRef<HTMLDivElement | null>(null);
const chartRef = useRef<MoexChart | null>(null);
const compareManagerRef = useRef<null | CompareManager>(null);
const timeframeRef = useRef<Timeframes | undefined>(moexChartState?.tf);
const savedDataRef = useRef<string | undefined>(moexChartState?.savedData);
const updateTimeframeRef = useRef<((tf: Timeframes) => void) | null>(null);
useEffect(() => {
timeframeRef.current = moexChartState?.tf;
savedDataRef.current = moexChartState?.savedData;
}, [moexChartState]);
updateTimeframeRef.current = (tf: Timeframes) => {
if (timeframeRef.current === tf) {
return;
}
timeframeRef.current = tf;
updateProperties((state) => {
state.moexChartState = {
...state.moexChartState,
tf,
};
});
};
const saveSnapshot = () => {
const snapshot = chartRef.current?.getSnapshot();
if (!snapshot) {
return;
}
const savedData = JSON.stringify(snapshot);
savedDataRef.current = savedData;
updateProperties((state) => {
state.moexChartState = {
...state.moexChartState,
tf: timeframeRef.current || Timeframes['1m'],
savedData,
};
});
};
const applySnapshot = () => {
if (!savedDataRef.current || !chartRef.current) {
return;
}
const savedSnapshot = JSON.parse(savedDataRef.current) as IMoexChart['snapshot'];
const timeframe = timeframeRef.current || Timeframes['1m'];
chartRef.current.setSnapshot({
...savedSnapshot,
charts: savedSnapshot.charts.map((chartSnapshot) => ({
...chartSnapshot,
symbol,
timeframe,
})),
});
compareManagerRef.current = chartRef.current.getCompareManager();
};
useEffect(() => {
const container = containerRef.current;
if (!container) {
return undefined;
}
const timeframe = timeframeRef.current || Timeframes['1m'];
const savedSnapshot = savedDataRef.current
? (JSON.parse(savedDataRef.current) as IMoexChart['snapshot'])
: MOEX_CHART_CONFIG.snapshot;
const chart = new MoexChart({
...MOEX_CHART_CONFIG,
container,
snapshot: {
...savedSnapshot,
charts: savedSnapshot.charts.map((chartSnapshot) => ({
...chartSnapshot,
symbol,
timeframe,
})),
},
chartCollectionPreset: {
...MOEX_CHART_CONFIG.chartCollectionPreset,
openCompareModal: () => setIsCompareOpen(true),
getDataSource: DataSourceProvider.getDataSource(indicativeData, (tf) => {
updateTimeframeRef.current?.(tf);
}),
startRealtime: (getSymbols, getTimeframe, update) =>
dataSourceProvider.startRealtime({
getSymbols,
getTimeframe,
update,
}),
},
});
chartRef.current = chart;
compareManagerRef.current = chart.getCompareManager();
return () => {
chartRef.current = null;
compareManagerRef.current = null;
chart.destroy();
};
}, [symbol, indicativeData]);
return {
containerRef,
isCompareOpen,
compareManagerRef,
setIsCompareOpen,
saveSnapshot,
applySnapshot,
hasSavedSnapshot: Boolean(moexChartState?.savedData),
};
};