매매 시그널 알림 화면 수정

This commit is contained in:
Macbook
2026-05-29 00:46:20 +09:00
parent cbad62a5b0
commit e43b5cbd5a
45 changed files with 2186 additions and 415 deletions
+31 -6
View File
@@ -16,6 +16,11 @@ import FibTZSettingsModal from './components/FibTZSettingsModal';
import ChartSlot, { type ChartSlotHandle } from './components/ChartSlot';
import { LAYOUTS, DEFAULT_SYNC, type LayoutDef, type SyncOptions } from './utils/layoutTypes';
import { generateBars, formatPrice, SYMBOLS } from './utils/dataGenerator';
import {
normalizeChartTimeFormat,
setChartTimeFormat,
useChartTimeFormat,
} from './utils/chartTimeFormat';
import { normalizeTimezone, setDisplayTimezone, useDisplayTimezone } from './utils/timezone';
import { calcStats, type PriceStats } from './utils/calculations';
import { getKoreanName } from './utils/marketNameCache';
@@ -47,6 +52,10 @@ import { useHistoryLoader, LOAD_MORE_TRIGGER } from './hooks/useHistoryLoader';
import { useMarketTicker } from './hooks/useMarketTicker';
import { useUpbitOrderbook } from './hooks/useUpbitOrderbook';
import { useIndicatorSettings } from './hooks/useIndicatorSettings';
import {
consumeSkipNextChartDefaultsSync,
markChartIndicatorSaveCommitted,
} from './utils/indicatorChartDefaultsSync';
import {
duplicateIndicatorInList,
mergeIndicators,
@@ -182,6 +191,7 @@ function App() {
const { defaults: appDefaults, isLoaded: appSettingsLoaded, save: saveAppDef } = useAppSettings(sessionKey);
const { permissions: menuPermissions, isLoaded: menuPermsLoaded, can: canMenu } = useMenuPermissions(sessionKey);
const displayTimezone = useDisplayTimezone();
const chartTimeFormat = useChartTimeFormat();
// DB 로드 전에는 localStorage 기본값, 로드 후 DB 값으로 오버라이드됨
const [symbol, setSymbol] = useState(initial.symbol);
@@ -253,8 +263,16 @@ function App() {
setDisplayTimezone(next);
saveAppDef({ displayTimezone: next });
const tf = layoutDef.count > 1 ? activeSlotTf : timeframe;
managerRef.current?.setDisplayTimezone(next, tf);
}, [saveAppDef, layoutDef.count, activeSlotTf, timeframe]);
managerRef.current?.setDisplayTimezone(next, tf, chartTimeFormat);
}, [saveAppDef, layoutDef.count, activeSlotTf, timeframe, chartTimeFormat]);
const handleChartTimeFormatChange = useCallback((format: string) => {
const next = normalizeChartTimeFormat(format);
setChartTimeFormat(next);
saveAppDef({ chartTimeFormat: next });
const tf = layoutDef.count > 1 ? activeSlotTf : timeframe;
managerRef.current?.setDisplayTimezone(displayTimezone, tf, next);
}, [saveAppDef, layoutDef.count, activeSlotTf, timeframe, displayTimezone]);
const chartSymbol = layoutDef.count > 1 ? activeSlotSymbol : symbol;
const { orderbook, wsStatus: obWsStatus, spread } = useUpbitOrderbook(chartSymbol);
@@ -957,8 +975,8 @@ function App() {
useEffect(() => {
if (!appSettingsLoaded) return;
const tf = layoutDef.count > 1 ? activeSlotTf : timeframe;
managerRef.current?.setDisplayTimezone(displayTimezone, tf);
}, [appSettingsLoaded, displayTimezone, timeframe, activeSlotTf, layoutDef.count]);
managerRef.current?.setDisplayTimezone(displayTimezone, tf, chartTimeFormat);
}, [appSettingsLoaded, displayTimezone, chartTimeFormat, timeframe, activeSlotTf, layoutDef.count]);
useEffect(() => {
if (!appSettingsLoaded) return;
@@ -1484,6 +1502,7 @@ function App() {
const fromTemplate =
isIndicatorSettingsTemplateId(settingsModalId ?? '')
|| updated.id.startsWith('template_');
markChartIndicatorSaveCommitted();
saveParams(updated.type, updated.params);
saveVisual(
updated.type,
@@ -1554,6 +1573,10 @@ function App() {
useLayoutEffect(() => {
if (!chartVisible) return;
if (indicatorSettingsRevision <= lastSyncedSettingsRevisionRef.current) return;
if (consumeSkipNextChartDefaultsSync()) {
lastSyncedSettingsRevisionRef.current = indicatorSettingsRevision;
return;
}
syncChartsFromSavedDefaults();
lastSyncedSettingsRevisionRef.current = indicatorSettingsRevision;
}, [chartVisible, indicatorSettingsRevision, syncChartsFromSavedDefaults]);
@@ -1756,7 +1779,7 @@ function App() {
)}
{/* ── 설정 화면 ──────────────────────────────────────────────────── */}
{menuPage === 'notifications' && (
{menuPage === 'notifications' && canMenu('notifications') && (
<TradeNotificationListPage
theme={theme}
tickers={marketTickers}
@@ -1885,6 +1908,8 @@ function App() {
onFcmPushEnabled={v => saveAppDef({ fcmPushEnabled: v })}
displayTimezone={displayTimezone}
onDisplayTimezoneChange={handleTimezoneChange}
chartTimeFormat={chartTimeFormat}
onChartTimeFormatChange={handleChartTimeFormatChange}
verificationIssueNotify={appDefaults.verificationIssueNotify}
onVerificationIssueNotify={v => saveAppDef({ verificationIssueNotify: v })}
onFcmTest={async () => {
@@ -2256,7 +2281,7 @@ function App() {
const wrapper = document.querySelector('.chart-wrapper') as HTMLElement | null;
mgr.setVolumeVisible(chartVolumeVisible, wrapper?.clientHeight);
mgr.setPaneSeparatorOptions(chartPaneSeparator);
mgr.setDisplayTimezone(displayTimezone, timeframe);
mgr.setDisplayTimezone(displayTimezone, timeframe, chartTimeFormat);
syncBacktestMarkersRef.current();
// 왼쪽 스크롤 감지 → 과거 데이터 추가 로드
mgr.subscribeVisibleLogicalRange(r => {