mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
fix: add HMR guard to prevent ConcurrentCallError on SDK double-init
При HMR Vite перевыполняет main.tsx, вызывая повторный init() и mount*() компонентов SDK. mountThemeParams() и другие бросают ConcurrentCallError асинхронно, что не ловится синхронным try/catch. Решение: флаг на window.__tg_sdk_initialized предотвращает повторную инициализацию при горячей перезагрузке модуля.
This commit is contained in:
101
src/main.tsx
101
src/main.tsx
@@ -26,54 +26,71 @@ import { getCachedFullscreenEnabled, isTelegramMobile } from './hooks/useTelegra
|
|||||||
import './i18n';
|
import './i18n';
|
||||||
import './styles/globals.css';
|
import './styles/globals.css';
|
||||||
|
|
||||||
// Safe mount helper — ignores "already mounted/mounting" errors (HMR, StrictMode)
|
// HMR guard — prevent double init when Vite hot-reloads the module
|
||||||
function safeMountSync(fn: () => void) {
|
const HMR_KEY = '__tg_sdk_initialized';
|
||||||
|
const alreadyInitialized = (window as unknown as Record<string, unknown>)[HMR_KEY] === true;
|
||||||
|
|
||||||
|
if (!alreadyInitialized) {
|
||||||
|
(window as unknown as Record<string, unknown>)[HMR_KEY] = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fn();
|
init();
|
||||||
} catch {
|
restoreInitData();
|
||||||
// Already mounted or not available
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Telegram SDK v3
|
// Mount components — each in its own try/catch so one failure doesn't block others
|
||||||
try {
|
try {
|
||||||
init();
|
mountMiniApp();
|
||||||
restoreInitData();
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mountThemeParams();
|
||||||
|
bindThemeParamsCssVars();
|
||||||
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mountSwipeBehavior();
|
||||||
|
disableVerticalSwipes();
|
||||||
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mountClosingBehavior();
|
||||||
|
disableClosingConfirmation();
|
||||||
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mountBackButton();
|
||||||
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mountMainButton();
|
||||||
|
} catch {
|
||||||
|
/* already mounted */
|
||||||
|
}
|
||||||
|
|
||||||
safeMountSync(() => mountMiniApp());
|
// Viewport — async, fullscreen зависит от смонтированного viewport
|
||||||
safeMountSync(() => {
|
mountViewport()
|
||||||
mountThemeParams();
|
.then(() => {
|
||||||
bindThemeParamsCssVars();
|
bindViewportCssVars();
|
||||||
});
|
expandViewport();
|
||||||
safeMountSync(() => {
|
|
||||||
mountSwipeBehavior();
|
|
||||||
disableVerticalSwipes();
|
|
||||||
});
|
|
||||||
safeMountSync(() => {
|
|
||||||
mountClosingBehavior();
|
|
||||||
disableClosingConfirmation();
|
|
||||||
});
|
|
||||||
safeMountSync(() => mountBackButton());
|
|
||||||
safeMountSync(() => mountMainButton());
|
|
||||||
|
|
||||||
// Viewport — async, fullscreen зависит от смонтированного viewport
|
// Auto-enter fullscreen if enabled in settings (mobile only)
|
||||||
mountViewport()
|
if (getCachedFullscreenEnabled() && isTelegramMobile()) {
|
||||||
.then(() => {
|
if (!isFullscreen()) {
|
||||||
bindViewportCssVars();
|
requestFullscreen();
|
||||||
expandViewport();
|
}
|
||||||
|
|
||||||
// Auto-enter fullscreen if enabled in settings (mobile only)
|
|
||||||
if (getCachedFullscreenEnabled() && isTelegramMobile()) {
|
|
||||||
if (!isFullscreen()) {
|
|
||||||
requestFullscreen();
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.catch(() => {});
|
||||||
.catch(() => {});
|
|
||||||
|
|
||||||
miniAppReady();
|
miniAppReady();
|
||||||
} catch {
|
} catch {
|
||||||
// Not in Telegram — ok
|
// Not in Telegram — ok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preload logo from cache immediately on page load
|
// Preload logo from cache immediately on page load
|
||||||
|
|||||||
Reference in New Issue
Block a user