import React from 'react'; import ReactDOM from 'react-dom/client'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { init, restoreInitData, retrieveRawInitData, mountMiniApp, miniAppReady, mountViewport, expandViewport, mountSwipeBehavior, disableVerticalSwipes, mountClosingBehavior, disableClosingConfirmation, mountBackButton, bindThemeParamsCssVars, bindViewportCssVars, requestFullscreen, isFullscreen, } from '@telegram-apps/sdk-react'; import { clearStaleSessionIfNeeded } from './utils/token'; import { AppWithNavigator } from './AppWithNavigator'; import { ErrorBoundary } from './components/ErrorBoundary'; import { initLogoPreload } from './api/branding'; import { getCachedFullscreenEnabled, isTelegramMobile } from './hooks/useTelegramSDK'; import './i18n'; import './styles/globals.css'; // HMR guard — prevent double init when Vite hot-reloads the module const HMR_KEY = '__tg_sdk_initialized'; const alreadyInitialized = (window as unknown as Record)[HMR_KEY] === true; if (!alreadyInitialized) { (window as unknown as Record)[HMR_KEY] = true; try { init(); restoreInitData(); // Сбрасываем старые токены если init data изменился (новая сессия Telegram) clearStaleSessionIfNeeded(retrieveRawInitData() || null); // Mount components — each in its own try/catch so one failure doesn't block others // Note: mountMiniApp() internally mounts themeParams in SDK v3, // so we don't call mountThemeParams() separately to avoid ConcurrentCallError try { mountMiniApp(); } catch { /* already mounted */ } try { bindThemeParamsCssVars(); } catch { /* theme params not yet available */ } try { mountSwipeBehavior(); disableVerticalSwipes(); } catch { /* already mounted */ } try { mountClosingBehavior(); disableClosingConfirmation(); } catch { /* already mounted */ } try { mountBackButton(); } catch { /* already mounted */ } // Viewport — async, fullscreen зависит от смонтированного viewport mountViewport() .then(() => { bindViewportCssVars(); expandViewport(); // Auto-enter fullscreen if enabled in settings (mobile only) if (getCachedFullscreenEnabled() && isTelegramMobile()) { if (!isFullscreen()) { requestFullscreen(); } } }) .catch(() => {}); miniAppReady(); } catch { // Not in Telegram — ok } } // Preload logo from cache — defer to idle time so it doesn't compete with LCP if ('requestIdleCallback' in window) { requestIdleCallback(() => initLogoPreload()); } else { setTimeout(initLogoPreload, 100); } const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false, }, }, }); ReactDOM.createRoot(document.getElementById('root')!).render( , );