가상매매 화면오류 수정
This commit is contained in:
@@ -178,6 +178,10 @@ interface TradingChartProps {
|
||||
custom1OverlayActive?: boolean;
|
||||
onCustom1OverlayActiveChange?: (active: boolean) => void;
|
||||
onOpenCustom1OverlaySettings?: () => void;
|
||||
/** 미니 차트 — plot 너비에 맞는 초기 x축 캔들 수 (미지정 시 DISPLAY_COUNT) */
|
||||
resolveInitialDisplayCount?: (plotWidth: number) => number;
|
||||
/** true — reload·layout 복구 타이머의 반복 viewport 재조정 생략 (미니 카드 깜빡임 방지) */
|
||||
skipViewportRecovery?: boolean;
|
||||
}
|
||||
|
||||
const TradingChart: React.FC<TradingChartProps> = ({
|
||||
@@ -231,6 +235,8 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
custom1OverlayActive,
|
||||
onCustom1OverlayActiveChange,
|
||||
onOpenCustom1OverlaySettings,
|
||||
resolveInitialDisplayCount,
|
||||
skipViewportRecovery = false,
|
||||
}) => {
|
||||
const effectiveShowChartRightToolbar = showChartRightToolbar ?? showPaneLegend;
|
||||
const showOverlayControlsOnly = !!(
|
||||
@@ -316,6 +322,17 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const recoveryTimerRef = useRef<number | null>(null);
|
||||
const resizeDebounceRef = useRef<number | null>(null);
|
||||
const chartVisibleRef = useRef(chartVisible);
|
||||
const resolveInitialDisplayCountRef = useRef(resolveInitialDisplayCount);
|
||||
const skipViewportRecoveryRef = useRef(skipViewportRecovery);
|
||||
const lastViewportFitRef = useRef<{ count: number; width: number } | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
resolveInitialDisplayCountRef.current = resolveInitialDisplayCount;
|
||||
}, [resolveInitialDisplayCount]);
|
||||
|
||||
useEffect(() => {
|
||||
skipViewportRecoveryRef.current = skipViewportRecovery;
|
||||
}, [skipViewportRecovery]);
|
||||
|
||||
const chartTimeFormat = useChartTimeFormat();
|
||||
const [chartMgr, setChartMgr] = useState<ChartManager | null>(null);
|
||||
@@ -548,15 +565,31 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
userDraggedRatioRef.current = null;
|
||||
}, [paneAreaRatio]);
|
||||
|
||||
const getInitialDisplayCount = useCallback((): number => {
|
||||
const plotW = containerRef.current?.clientWidth ?? wrapperRef.current?.clientWidth ?? 0;
|
||||
const resolver = resolveInitialDisplayCountRef.current;
|
||||
return resolver ? resolver(plotW) : DISPLAY_COUNT;
|
||||
}, []);
|
||||
|
||||
const applyInitialVisibleRange = useCallback((mgr: ChartManager) => {
|
||||
const plotW = containerRef.current?.clientWidth ?? wrapperRef.current?.clientWidth ?? 0;
|
||||
if (plotW <= 0) return;
|
||||
const count = getInitialDisplayCount();
|
||||
const prev = lastViewportFitRef.current;
|
||||
if (prev && prev.count === count && Math.abs(prev.width - plotW) < 4) return;
|
||||
lastViewportFitRef.current = { count, width: plotW };
|
||||
const fb = mgr.hasIchimoku() ? 28 : 0;
|
||||
mgr.setInitialVisibleRange(count, fb);
|
||||
}, [getInitialDisplayCount]);
|
||||
|
||||
/** pane 레이아웃 + 가격·시간축 정상화 (느린 네트워크·레이아웃 지연 후 복구용) */
|
||||
const normalizeChartViewport = useCallback((mgr: ChartManager) => {
|
||||
applyPaneLayout(mgr);
|
||||
requestAnimationFrame(() => {
|
||||
try { mgr.autoScale(); } catch { /* ok */ }
|
||||
const fb = mgr.hasIchimoku() ? 28 : 0;
|
||||
mgr.setInitialVisibleRange(DISPLAY_COUNT, fb);
|
||||
applyInitialVisibleRange(mgr);
|
||||
});
|
||||
}, [applyPaneLayout]);
|
||||
}, [applyPaneLayout, applyInitialVisibleRange]);
|
||||
|
||||
/** 캔들 확대 보기 → 원복 직후 가격·시간축·pane 비율 정상화 */
|
||||
useEffect(() => {
|
||||
@@ -573,13 +606,12 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const wrapperH = wrapperRef.current?.clientHeight ?? 0;
|
||||
m.restoreFromCandleFullscreen(wrapperH);
|
||||
applyPaneLayout(m);
|
||||
const futureBars = m.hasIchimoku() ? 28 : 0;
|
||||
m.setInitialVisibleRange(DISPLAY_COUNT, futureBars);
|
||||
applyInitialVisibleRange(m);
|
||||
};
|
||||
requestAnimationFrame(() => requestAnimationFrame(runRestore));
|
||||
[200, 500, 1000].forEach(delay => setTimeout(runRestore, delay));
|
||||
}
|
||||
}, [candleOnlyMode, chartMgr, applyPaneLayout]);
|
||||
}, [candleOnlyMode, chartMgr, applyPaneLayout, applyInitialVisibleRange]);
|
||||
|
||||
// ── 전체 재로드 (데이터 + 인디케이터) ─────────────────────────────────────
|
||||
const reloadSafetyTimers = useRef<ReturnType<typeof setTimeout>[]>([]);
|
||||
@@ -778,11 +810,10 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
requestAnimationFrame(() => {
|
||||
applyPaneLayout(mgr);
|
||||
requestAnimationFrame(() => {
|
||||
const futureBars = mgr.hasIchimoku() ? 28 : 0;
|
||||
mgr.setInitialVisibleRange(DISPLAY_COUNT, futureBars);
|
||||
applyInitialVisibleRange(mgr);
|
||||
});
|
||||
});
|
||||
}, [applyPaneLayout]);
|
||||
}, [applyPaneLayout, applyInitialVisibleRange]);
|
||||
|
||||
const reloadAll = useCallback(async (
|
||||
mgr: ChartManager,
|
||||
@@ -887,6 +918,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
queueIndicatorRecovery();
|
||||
return;
|
||||
}
|
||||
if (skipViewportRecoveryRef.current) return;
|
||||
const w = wrapperRef.current;
|
||||
if (!w || w.clientHeight < MIN_VALID_LAYOUT_HEIGHT) return;
|
||||
normalizeChartViewport(m);
|
||||
@@ -1233,8 +1265,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
if (savedLR) {
|
||||
m.applyVisibleLogicalRange(savedLR.from, savedLR.to);
|
||||
} else {
|
||||
const fb = m.hasIchimoku() ? 28 : 0;
|
||||
m.setInitialVisibleRange(DISPLAY_COUNT, fb);
|
||||
applyInitialVisibleRange(m);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1528,10 +1559,11 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const layoutRecoveryAttemptedRef = useRef(false);
|
||||
useEffect(() => {
|
||||
layoutRecoveryAttemptedRef.current = false;
|
||||
lastViewportFitRef.current = null;
|
||||
}, [market, timeframe]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chartVisible) return;
|
||||
if (!chartVisible || skipViewportRecovery) return;
|
||||
const mgr = managerRef.current;
|
||||
if (!mgr || !chartMgr || bars.length < 2) return;
|
||||
if (!canApplyChartBars(bars, barsMarket, market)) return;
|
||||
@@ -1561,7 +1593,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
);
|
||||
|
||||
return () => { timers.forEach(clearTimeout); };
|
||||
}, [chartMgr, bars.length, barsMarket, market, chartVisible, normalizeChartViewport]);
|
||||
}, [chartMgr, bars.length, barsMarket, market, chartVisible, normalizeChartViewport, skipViewportRecovery]);
|
||||
|
||||
// 데이터는 준비됐으나 메인 시리즈가 없는 빈 차트 자동 복구 (종목 전환·레이아웃 전환 직후)
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user