import React, { lazy, Suspense, useEffect, useState } from 'react'; import { Capacitor } from '@capacitor/core'; import { StatusBar, Style } from '@capacitor/status-bar'; import { SplashScreen as CapSplashScreen } from '@capacitor/splash-screen'; import { AuthProvider, useAuth } from './contexts/AuthContext'; import { NavigationProvider, useNavigation } from './contexts/NavigationContext'; import { TradeNotificationProvider, useTradeNotification } from './contexts/TradeNotificationContext'; import { useAppSettings, resolveAppDefaults } from './hooks/useAppSettings'; import TabBar, { type TabId } from './components/TabBar'; import LiveSignalBridge from './components/LiveSignalBridge'; import AppUpdateGate from './components/AppUpdateGate'; import LoginScreen from './screens/LoginScreen'; import '@frontend/styles/splashScreen.css'; import './theme/global.css'; const VirtualTradingScreen = lazy(() => import('./screens/virtual/VirtualTradingScreen')); const StrategyEditorScreen = lazy(() => import('./screens/strategy/StrategyEditorScreen')); const NotificationsScreen = lazy(() => import('./screens/notifications/NotificationsScreen')); const SettingsScreen = lazy(() => import('./screens/settings/SettingsScreen')); function ToastStack() { const { toastNotifications, dismissToast } = useTradeNotification(); if (toastNotifications.length === 0) return null; return (
{toastNotifications.slice(0, 3).map(t => (
dismissToast(t.id)}> {t.signalType === 'BUY' ? '매수' : '매도'} {' '}{t.market} · ₩{t.price?.toLocaleString()}
))}
); } function MainApp() { const { tab, setTab, openVirtualFocus, goVirtualList, goNotifyList } = useNavigation(); const { unreadCount } = useTradeNotification(); const { sessionKey } = useAuth(); const { settings, isLoaded } = useAppSettings(sessionKey); const defaults = resolveAppDefaults(settings); /** FCM/알림 권한: 로그인·메인 진입 시 호출하지 않음 — 설정 버튼에서만 */ useEffect(() => { document.documentElement.setAttribute('data-theme', defaults.theme ?? 'dark'); }, [defaults.theme]); useEffect(() => { if (tab === 'virtual') goNotifyList(); else if (tab === 'notifications') goVirtualList(); }, [tab, goVirtualList, goNotifyList]); const screens: Record = { virtual: , strategy: , notifications: , settings: , }; return (
로딩…
}> {screens[tab]} ); } function AppRoot() { const { authReady, isAppEntered, handleLoginSuccess, handleGuestEnter, sessionKey, } = useAuth(); const [nativeReady, setNativeReady] = useState(false); useEffect(() => { void (async () => { if (Capacitor.isNativePlatform()) { try { await StatusBar.setStyle({ style: Style.Dark }); await StatusBar.setBackgroundColor({ color: '#0f0f23' }); await CapSplashScreen.hide(); } catch { /* web dev */ } } setNativeReady(true); })(); }, []); if (!authReady || !nativeReady) { return
GoldenChart
; } if (!isAppEntered) { return ( ); } return ( ); } export default function App() { return ( ); }