diff --git a/frontend/src/App.css b/frontend/src/App.css index e3cbaf8..f083690 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -12394,6 +12394,18 @@ html.theme-light .tam-disclaimer { color: #90a4ae; } flex: 1; line-height: 1.35; } +/* 실시간 차트 상단 툴바 — 알림 팝업 위치 선택 */ +.tv-toolbar-right .tmb-notify-layout-trigger { + width: 30px; + height: 30px; + border: none; + background: transparent; +} +.tv-toolbar-right .tmb-notify-layout-trigger:hover, +.tv-toolbar-right .tmb-notify-layout-trigger--open { + background: var(--bg3); + border: none; +} .tmb-notify-layout-cols-row { display: flex; align-items: center; diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 368be89..f3f7942 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -671,7 +671,6 @@ function App() { saveAllIndicatorDefaults={saveAllIndicatorDefaults} indicatorSettingsRevision={indicatorSettingsRevision} onOpenNotificationsPage={openNotificationsPage} - onOpenAppDownload={() => setAppDownloadOpen(true)} /> ) : null; diff --git a/frontend/src/chart/ChartWorkspaceView.tsx b/frontend/src/chart/ChartWorkspaceView.tsx index 880a181..1b4dc3c 100644 --- a/frontend/src/chart/ChartWorkspaceView.tsx +++ b/frontend/src/chart/ChartWorkspaceView.tsx @@ -58,7 +58,6 @@ import { fmtListTimestamp } from '../utils/backtestUiUtils'; export interface ChartWorkspaceViewProps { onOpenNotificationsPage: () => void; - onOpenAppDownload: () => void; symbol: string; timeframe: Timeframe; chartType: ChartType; @@ -315,7 +314,7 @@ export interface ChartWorkspaceViewProps { function ChartWorkspaceViewInner(props: ChartWorkspaceViewProps) { const { - onOpenNotificationsPage, onOpenAppDownload, + onOpenNotificationsPage, symbol, timeframe, chartType, theme, mode, logScale, showGrid, toolbarActiveIndicators, layoutDef, syncOptions, activeSlot, activeSlotSymbol, activeSlotTf, slot0InitProps, slotInitProps, @@ -383,7 +382,6 @@ function ChartWorkspaceViewInner(props: ChartWorkspaceViewProps) { <> 1 ? activeSlotTf : timeframe} chartType={chartType} theme={theme} mode={mode} logScale={logScale} showGrid={showGrid} activeIndicators={toolbarActiveIndicators} @@ -516,6 +514,12 @@ function ChartWorkspaceViewInner(props: ChartWorkspaceViewProps) { chartQuoteError={error} priceExtremeLabelsVisible={chartPriceExtremeLabelsVisible} onTogglePriceExtremeLabels={handleTogglePriceExtremeLabels} + tradeAlertPopupPosition={appDefaults.tradeAlertPopupPosition} + tradeAlertPopupLayout={appDefaults.tradeAlertPopupLayout} + tradeAlertPopupGridCols={appDefaults.tradeAlertPopupGridCols} + onTradeAlertPopupPosition={v => saveAppDef({ tradeAlertPopupPosition: v })} + onTradeAlertPopupLayout={v => saveAppDef({ tradeAlertPopupLayout: v })} + onTradeAlertPopupGridCols={v => saveAppDef({ tradeAlertPopupGridCols: v })} /> {isMobile && (showMarketPanel || mobileRightOpen) && ( diff --git a/frontend/src/chart/useChartWorkspace.ts b/frontend/src/chart/useChartWorkspace.ts index 528f209..afff8c8 100644 --- a/frontend/src/chart/useChartWorkspace.ts +++ b/frontend/src/chart/useChartWorkspace.ts @@ -164,7 +164,6 @@ export interface UseChartWorkspaceParams { saveAllIndicatorDefaults: ReturnType['saveAllIndicatorDefaults']; indicatorSettingsRevision: number; onOpenNotificationsPage: () => void; - onOpenAppDownload: () => void; } export interface SettingsPageChartBindings { @@ -223,7 +222,6 @@ export function useChartWorkspace({ saveAllIndicatorDefaults: _saveAllIndicatorDefaults, indicatorSettingsRevision, onOpenNotificationsPage, - onOpenAppDownload, }: UseChartWorkspaceParams) { void _saveAllIndicatorDefaults; const initial = loadState(); @@ -1969,7 +1967,6 @@ export function useChartWorkspace({ const viewProps: ChartWorkspaceViewProps = { onOpenNotificationsPage, - onOpenAppDownload, symbol, timeframe, chartType, theme, mode, logScale, showGrid, toolbarActiveIndicators, layoutDef, syncOptions, activeSlot, activeSlotSymbol, activeSlotTf, slot0InitProps, slotInitProps, diff --git a/frontend/src/components/NotifyUiBindings.tsx b/frontend/src/components/NotifyUiBindings.tsx index 5dee0ad..436beda 100644 --- a/frontend/src/components/NotifyUiBindings.tsx +++ b/frontend/src/components/NotifyUiBindings.tsx @@ -51,10 +51,8 @@ import Toolbar, { type ToolbarProps } from './Toolbar'; export const ChartToolbarNotify: React.FC void; - onOpenAppDownload?: () => void; }> = ({ onOpenNotifyList, - onOpenAppDownload, ...toolbarProps }) => { const { unreadCount } = useTradeNotification(); @@ -63,7 +61,6 @@ export const ChartToolbarNotify: React.FC ); }; diff --git a/frontend/src/components/Toolbar.tsx b/frontend/src/components/Toolbar.tsx index f2cd2a8..5518b01 100644 --- a/frontend/src/components/Toolbar.tsx +++ b/frontend/src/components/Toolbar.tsx @@ -42,6 +42,7 @@ import { type ChartLiveQuote, } from '../utils/chartLiveQuote'; import LayoutPicker from './LayoutPicker'; +import TradeAlertPopupMenubarSelect from './TradeAlertPopupMenubarSelect'; import { DEFAULT_SYNC, type LayoutDef, type SyncOptions } from '../utils/layoutTypes'; import { loadStrategies } from '../utils/backendApi'; @@ -91,8 +92,6 @@ export interface ToolbarProps { /** 매매 시그널 알림 (미확인 개수) */ tradeNotifyUnread?: number; onOpenTradeNotifications?: () => void; - /** 모바일 앱 다운로드 */ - onOpenAppDownload?: () => void; /** 자석모드 현재 상태 */ magnetMode?: 'off' | 'weak' | 'strong'; /** 자석모드 토글 (off↔strong) */ @@ -146,6 +145,13 @@ export interface ToolbarProps { /** 9·20일 신고가·신저가 차트 표시 (실시간 차트 상단 툴바) */ priceExtremeLabelsVisible?: boolean; onTogglePriceExtremeLabels?: () => void; + /** 매매 알림 팝업 표시 위치·방식 */ + tradeAlertPopupPosition?: string; + tradeAlertPopupLayout?: string; + tradeAlertPopupGridCols?: number; + onTradeAlertPopupPosition?: (v: import('../utils/tradeAlertPopupLayout').TradeAlertPopupPosition) => void; + onTradeAlertPopupLayout?: (v: import('../utils/tradeAlertPopupLayout').TradeAlertPopupLayout) => void; + onTradeAlertPopupGridCols?: (v: number) => void; } // ─── SVG 아이콘 ──────────────────────────────────────────────────────────── @@ -229,14 +235,6 @@ const IcBell = () => ( ); -/** 모바일 앱 다운로드 */ -const IcAppDownload = () => ( - - - - - -); /** 매매 시그널 알림 (번개 아이콘으로 가격 알림 벨과 구분) */ const IcTradeSignal = () => ( @@ -814,7 +812,7 @@ const Toolbar: React.FC = ({ onFitContent, onScrollToNow, onAddIndicator, onAddIndicators, onIndicatorOrderChange, onRemoveByType, onAutoFib, onClearFib, onScreenshot, onToggleStats, onToggleWatch, onToggleAlert, - tradeNotifyUnread = 0, onOpenTradeNotifications, onOpenAppDownload, + tradeNotifyUnread = 0, onOpenTradeNotifications, magnetMode = 'off', onToggleMagnet, onUndo, onRedo, canUndo, canRedo, onClearDrawings, onToggleGrid, @@ -837,6 +835,12 @@ const Toolbar: React.FC = ({ chartQuoteError = null, priceExtremeLabelsVisible = false, onTogglePriceExtremeLabels, + tradeAlertPopupPosition, + tradeAlertPopupLayout, + tradeAlertPopupGridCols, + onTradeAlertPopupPosition, + onTradeAlertPopupLayout, + onTradeAlertPopupGridCols, }) => { const [showMarket, setShowMarket] = React.useState(false); const [showTfMenu, setShowTfMenu] = React.useState(false); @@ -1371,18 +1375,19 @@ const Toolbar: React.FC = ({ )} - {onOpenAppDownload && ( - - )} {onOpenTradeNotifications && ( - + <> + {(onTradeAlertPopupPosition || onTradeAlertPopupLayout) && ( + + )} +