Skip to content
This repository was archived by the owner on Jul 15, 2025. It is now read-only.

Commit 1190a39

Browse files
committed
feat: handle instrument change for chart
1 parent e41a4db commit 1190a39

File tree

3 files changed

+102
-10
lines changed

3 files changed

+102
-10
lines changed

src/api/services/chart/chart-sse.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ const activeSubscriptions = new Map<
1414
}
1515
>();
1616

17+
// Function to clear all active subscriptions and history cache
18+
export const clearChartCache = () => {
19+
// Unsubscribe from all active subscriptions
20+
activeSubscriptions.forEach((subscription) => {
21+
subscription.unsubscribe();
22+
});
23+
24+
// Clear the maps
25+
activeSubscriptions.clear();
26+
historyCache.clear();
27+
};
28+
1729
/**
1830
* Subscribes to candle data stream for a specific symbol
1931
* @param symbol The symbol to subscribe to
@@ -273,7 +285,8 @@ export const handleChartForget = async (request: any): Promise<{ msg_type: strin
273285
* @returns Promise resolving to forget_all response
274286
*/
275287
export const handleChartForgetStream = async (): Promise<{ msg_type: string }> => {
276-
// The actual unsubscription is handled by the returned function from handleChartSubscribe
277-
// This function is just for compatibility with the existing API
288+
// Unsubscribe from all active subscriptions
289+
clearChartCache();
290+
278291
return { msg_type: "forget_all" };
279292
};

src/components/Chart/Chart.tsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
handleChartForgetStream,
1010
} from "@/api/services/chart";
1111
import { ToolbarWidgets } from "./Components";
12+
import { useTradeStore } from "@/stores/tradeStore";
1213

1314
export const TradeChart: React.FC = () => {
1415
const ref = useRef<{
@@ -19,13 +20,24 @@ export const TradeChart: React.FC = () => {
1920
const { isMobile, isDesktop } = useDeviceDetection();
2021
const [chartType, setChartType] = useState("line"); // "line", "candles", "hollow"
2122
const [granularity, setGranularity] = useState(0); // 0 for tick, 60 for 1m candles, etc.
23+
const instrument = useTradeStore((state) => state.instrument);
2224

23-
// Mock API request handlers
25+
// API request handlers
2426
const requestAPI = (request: any) => {
27+
// If the request is for ticks_history, use the current instrument
28+
if (request.ticks_history) {
29+
request.ticks_history = instrument;
30+
}
2531
return handleChartApiRequest(request);
2632
};
2733

2834
const requestSubscribe = (request: any, callback: any) => {
35+
// If the request is for ticks or ticks_history, use the current instrument
36+
if (request.ticks) {
37+
request.ticks = instrument;
38+
} else if (request.ticks_history) {
39+
request.ticks_history = instrument;
40+
}
2941
return handleChartSubscribe(request, callback);
3042
};
3143

@@ -37,6 +49,28 @@ export const TradeChart: React.FC = () => {
3749
return handleChartForgetStream();
3850
};
3951

52+
// When instrument changes, forget all existing streams and force chart reload
53+
const [chartKey, setChartKey] = useState(instrument);
54+
const [isChartLoading, setIsChartLoading] = useState(false);
55+
56+
useEffect(() => {
57+
// Set loading state
58+
setIsChartLoading(true);
59+
60+
// Clear all existing streams
61+
requestForgetStream();
62+
63+
// Change the key to force a complete re-render of the SmartChart component
64+
setChartKey(instrument);
65+
66+
// Set a timeout to hide the loader after a short delay
67+
const loadingTimeout = setTimeout(() => {
68+
setIsChartLoading(false);
69+
}, 1500); // 1.5 seconds should be enough for most chart loads
70+
71+
return () => clearTimeout(loadingTimeout);
72+
}, [instrument]);
73+
4074
// Update chart type and granularity
4175
const updateChartType = (type: string) => {
4276
// First, forget all existing streams to ensure clean state
@@ -92,6 +126,14 @@ export const TradeChart: React.FC = () => {
92126

93127
return (
94128
<div className="flex h-full relative bg-theme border-r text-gray-100">
129+
{isChartLoading && (
130+
<div className="absolute inset-0 z-10 flex items-center justify-center bg-theme bg-opacity-80">
131+
<div className="text-center">
132+
<div className="inline-block animate-spin rounded-full h-8 w-8 border-4 border-solid border-blue-500 border-r-transparent"></div>
133+
<p className="mt-4 text-white">Loading chart data...</p>
134+
</div>
135+
</div>
136+
)}
95137
<Suspense
96138
fallback={
97139
<div className="flex items-center justify-center h-full w-full">
@@ -103,8 +145,10 @@ export const TradeChart: React.FC = () => {
103145
}
104146
>
105147
<SmartChart
148+
key={chartKey} // Add key to force re-render when instrument changes
106149
ref={ref}
107150
id="trade-chart"
151+
symbol={instrument} // Explicitly pass the instrument as symbol
108152
barriers={[]}
109153
chartStatusListener={() => null}
110154
crosshair={0}

src/components/ContractDetailsChart/ContractDetailsChart.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
handleChartSubscribe,
99
handleChartForget,
1010
handleChartForgetStream,
11+
clearChartCache,
1112
} from "@/api/services/chart";
1213
import { getContractReplayData, closeContractStream } from "@/utils/contractApi";
1314
import { createChartMarkers } from "@/utils/chart-markers";
@@ -300,10 +301,20 @@ export const ContractDetailsChart: React.FC<ContractDetailsChartProps> = ({
300301

301302
// API request handlers
302303
const requestAPI = (request: any) => {
304+
// If the request is for ticks_history, use the effective symbol
305+
if (request.ticks_history) {
306+
request.ticks_history = effectiveSymbol;
307+
}
303308
return handleChartApiRequest(request);
304309
};
305310

306311
const requestSubscribe = (request: any, callback: any) => {
312+
// If the request is for ticks or ticks_history, use the effective symbol
313+
if (request.ticks) {
314+
request.ticks = effectiveSymbol;
315+
} else if (request.ticks_history) {
316+
request.ticks_history = effectiveSymbol;
317+
}
307318
return handleChartSubscribe(request, callback);
308319
};
309320

@@ -315,13 +326,27 @@ export const ContractDetailsChart: React.FC<ContractDetailsChartProps> = ({
315326
return handleChartForgetStream();
316327
};
317328

318-
// Chart state change listener
319-
const chartStateChange = (state: string) => {
320-
setChartState(state);
321-
if (state === "READY") {
322-
setIsChartReady(true);
323-
}
324-
};
329+
// When effectiveSymbol changes, forget all existing streams and force chart reload
330+
const [chartKey, setChartKey] = useState(effectiveSymbol);
331+
const [isChartLoading, setIsChartLoading] = useState(false);
332+
333+
useEffect(() => {
334+
// Set loading state
335+
setIsChartLoading(true);
336+
337+
// Clear all existing streams
338+
clearChartCache();
339+
340+
// Change the key to force a complete re-render of the SmartChart component
341+
setChartKey(effectiveSymbol);
342+
343+
// Set a timeout to hide the loader after a short delay
344+
const loadingTimeout = setTimeout(() => {
345+
setIsChartLoading(false);
346+
}, 1500); // 1.5 seconds should be enough for most chart loads
347+
348+
return () => clearTimeout(loadingTimeout);
349+
}, [effectiveSymbol]);
325350

326351
// Create markers for entry and exit spots using the chart-markers utility
327352
const markers_array = useMemo(() => {
@@ -513,6 +538,14 @@ export const ContractDetailsChart: React.FC<ContractDetailsChartProps> = ({
513538
className={`relative bg-theme shadow-md rounded-lg overflow-hidden ${isLandscape ? "h-full" : "h-[400px]"}`}
514539
>
515540
<div className="absolute inset-0 rounded-lg overflow-hidden">
541+
{isChartLoading && (
542+
<div className="absolute inset-0 z-10 flex items-center justify-center bg-theme bg-opacity-80 rounded-lg">
543+
<div className="text-center">
544+
<div className="inline-block animate-spin rounded-full h-8 w-8 border-4 border-solid border-blue-500 border-r-transparent"></div>
545+
<p className="mt-4 text-white">Loading chart data...</p>
546+
</div>
547+
</div>
548+
)}
516549
<Suspense
517550
fallback={
518551
<div className="flex items-center justify-center h-full w-full">
@@ -524,8 +557,10 @@ export const ContractDetailsChart: React.FC<ContractDetailsChartProps> = ({
524557
}
525558
>
526559
<SmartChart
560+
key={chartKey} // Add key to force re-render when symbol changes
527561
ref={ref}
528562
id="replay-chart"
563+
symbol={effectiveSymbol} // Explicitly pass the effective symbol
529564
barriers={barriers_array}
530565
chartStatusListener={(isChartReady: boolean) => {
531566
setIsChartReady(isChartReady);

0 commit comments

Comments
 (0)