fix: revert to native Telegram WebApp API, remove SDK usage

This commit is contained in:
c0mrade
2026-02-01 20:37:23 +03:00
parent e5ea09dd3a
commit 6f8bc4fca5
2 changed files with 207 additions and 361 deletions

View File

@@ -1,9 +1,4 @@
import { useCallback, useMemo, useSyncExternalStore } from 'react';
import { init, viewport, miniApp, swipeBehavior, themeParams } from '@tma.js/sdk-react';
// SDK initialization state
let sdkInitialized = false;
let initCleanup: VoidFunction | null = null;
import { useCallback, useMemo } from 'react';
const FULLSCREEN_CACHE_KEY = 'cabinet_fullscreen_enabled';
@@ -48,7 +43,6 @@ export function isTelegramMobile(): boolean {
/**
* Get Telegram init data for authentication
* Returns the raw initData string used for backend authentication
*/
export function getTelegramInitData(): string | null {
const webApp = window.Telegram?.WebApp;
@@ -56,86 +50,31 @@ export function getTelegramInitData(): string | null {
}
/**
* Initialize Telegram SDK
* Call this once at app startup (in main.tsx)
* Initialize Telegram WebApp (basic setup without SDK)
*/
export function initTelegramSDK() {
// Only run in Telegram context
if (!isInTelegramWebApp()) {
return;
}
// Prevent double initialization
if (sdkInitialized) {
return;
}
const tg = window.Telegram?.WebApp;
if (!tg) return;
try {
// Initialize the SDK
initCleanup = init();
sdkInitialized = true;
// Basic initialization
tg.ready();
tg.expand();
// Mount mini app and call ready (sync)
miniApp.mount();
miniApp.ready();
// Disable closing confirmation by default
tg.disableClosingConfirmation?.();
// Mount theme params and bind CSS variables (sync)
try {
themeParams.mount();
themeParams.bindCssVars();
} catch {
// Theme params may already be mounted or not supported
}
// Disable vertical swipes if supported (sync)
try {
if (swipeBehavior.isSupported()) {
swipeBehavior.mount();
swipeBehavior.disableVertical();
// Auto-enter fullscreen if enabled in settings (mobile only)
const fullscreenEnabled = getCachedFullscreenEnabled();
if (fullscreenEnabled && isTelegramMobile() && tg.requestFullscreen) {
setTimeout(() => {
if (!tg.isFullscreen) {
tg.requestFullscreen?.();
}
} catch {
// Swipe behavior not available
}
// Mount viewport and bind CSS variables (async)
viewport
.mount()
.then(() => {
viewport.bindCssVars();
// Expand the mini app
viewport.expand();
// Auto-enter fullscreen if enabled in settings (mobile only)
const fullscreenEnabled = getCachedFullscreenEnabled();
if (fullscreenEnabled && isTelegramMobile()) {
try {
const isFullscreen = viewport.isFullscreen();
if (!isFullscreen) {
viewport.requestFullscreen().catch((e) => {
console.warn('Auto-fullscreen failed:', e);
});
}
} catch {
// Viewport signal not available
}
}
})
.catch((err) => {
console.warn('Viewport mount failed:', err);
});
} catch (e) {
console.warn('Telegram SDK initialization failed:', e);
}
}
/**
* Cleanup SDK (call on app unmount if needed)
*/
export function cleanupTelegramSDK() {
if (initCleanup) {
initCleanup();
initCleanup = null;
sdkInitialized = false;
}, 100);
}
}
@@ -153,79 +92,59 @@ export type TelegramPlatform =
| 'unknown'
| undefined;
// Default values for when SDK is not available
// Default values
const defaultInsets = { top: 0, bottom: 0, left: 0, right: 0 };
/**
* Helper to subscribe to SDK signals using useSyncExternalStore pattern
* Safely handles unmounted components by returning default values
*/
function useSDKSignal<T>(
signal: { (): T; sub(fn: VoidFunction): VoidFunction } | null,
defaultValue: T,
): T {
return useSyncExternalStore(
(callback) => {
if (!signal) return () => {};
try {
return signal.sub(callback);
} catch {
// Signal not available (component unmounted)
return () => {};
}
},
() => {
if (!signal) return defaultValue;
try {
return signal();
} catch {
// Signal not available (component unmounted)
return defaultValue;
}
},
() => defaultValue,
);
}
/**
* Hook for Telegram SDK integration
* Provides fullscreen mode, safe area insets, platform info, and other features
* Hook for Telegram WebApp integration
* Uses native window.Telegram.WebApp API
*/
export function useTelegramSDK() {
const inTelegram = isInTelegramWebApp();
const isReady = inTelegram && sdkInitialized;
const tg = window.Telegram?.WebApp;
// Get platform from window.Telegram.WebApp (always available in Telegram)
const platform = useMemo<TelegramPlatform>(() => {
if (!inTelegram) return undefined;
return window.Telegram?.WebApp?.platform as TelegramPlatform;
}, [inTelegram]);
return tg?.platform as TelegramPlatform;
}, [inTelegram, tg?.platform]);
// Use SDK signals for reactive state
const isFullscreen = useSDKSignal(isReady ? viewport.isFullscreen : null, false);
const safeAreaInsets = useSDKSignal(isReady ? viewport.safeAreaInsets : null, defaultInsets);
const contentSafeAreaInsets = useSDKSignal(
isReady ? viewport.contentSafeAreaInsets : null,
defaultInsets,
);
const viewportHeight = useSDKSignal(isReady ? viewport.height : null, 0);
const viewportStableHeight = useSDKSignal(isReady ? viewport.stableHeight : null, 0);
const viewportWidth = useSDKSignal(isReady ? viewport.width : null, 0);
const isExpanded = useSDKSignal(isReady ? viewport.isExpanded : null, true);
const isMobile = platform === 'ios' || platform === 'android';
// Safe area insets from Telegram WebApp
const safeAreaInset = useMemo(() => {
if (!inTelegram || !tg?.safeAreaInset) return defaultInsets;
return {
top: tg.safeAreaInset.top || 0,
bottom: tg.safeAreaInset.bottom || 0,
left: tg.safeAreaInset.left || 0,
right: tg.safeAreaInset.right || 0,
};
}, [inTelegram, tg?.safeAreaInset]);
const contentSafeAreaInset = useMemo(() => {
if (!inTelegram || !tg?.contentSafeAreaInset) return defaultInsets;
return {
top: tg.contentSafeAreaInset.top || 0,
bottom: tg.contentSafeAreaInset.bottom || 0,
left: tg.contentSafeAreaInset.left || 0,
right: tg.contentSafeAreaInset.right || 0,
};
}, [inTelegram, tg?.contentSafeAreaInset]);
const isFullscreen = tg?.isFullscreen ?? false;
const viewportHeight = tg?.viewportHeight ?? 0;
const viewportStableHeight = tg?.viewportStableHeight ?? 0;
const isExpanded = tg?.isExpanded ?? true;
const requestFullscreen = useCallback(() => {
if (!isReady) return;
viewport.requestFullscreen().catch((e) => {
console.warn('Fullscreen not supported:', e);
});
}, [isReady]);
if (!inTelegram || !tg?.requestFullscreen) return;
tg.requestFullscreen();
}, [inTelegram, tg]);
const exitFullscreen = useCallback(() => {
if (!isReady) return;
viewport.exitFullscreen().catch((e) => {
console.warn('Exit fullscreen failed:', e);
});
}, [isReady]);
if (!inTelegram || !tg?.exitFullscreen) return;
tg.exitFullscreen();
}, [inTelegram, tg]);
const toggleFullscreen = useCallback(() => {
if (isFullscreen) {
@@ -236,58 +155,31 @@ export function useTelegramSDK() {
}, [isFullscreen, requestFullscreen, exitFullscreen]);
const expand = useCallback(() => {
if (!isReady) return;
try {
viewport.expand();
} catch {
// Viewport not available
}
}, [isReady]);
if (!inTelegram || !tg?.expand) return;
tg.expand();
}, [inTelegram, tg]);
const disableVerticalSwipes = useCallback(() => {
if (!isReady) return;
try {
if (swipeBehavior.isSupported()) {
swipeBehavior.disableVertical();
}
} catch {
// Swipe behavior not available
}
}, [isReady]);
if (!inTelegram || !tg?.disableVerticalSwipes) return;
tg.disableVerticalSwipes();
}, [inTelegram, tg]);
const enableVerticalSwipes = useCallback(() => {
if (!isReady) return;
try {
if (swipeBehavior.isSupported()) {
swipeBehavior.enableVertical();
}
} catch {
// Swipe behavior not available
}
}, [isReady]);
if (!inTelegram || !tg?.enableVerticalSwipes) return;
tg.enableVerticalSwipes();
}, [inTelegram, tg]);
// Check if fullscreen is supported (Bot API 8.0+)
const isFullscreenSupported = useMemo(() => {
if (!isReady) return false;
try {
return typeof viewport.requestFullscreen === 'function';
} catch {
return false;
}
}, [isReady]);
// Check if it's mobile platform
const isMobile = platform === 'ios' || platform === 'android';
const isFullscreenSupported = inTelegram && typeof tg?.requestFullscreen === 'function';
return {
isTelegramWebApp: inTelegram,
isFullscreen,
isFullscreenSupported,
safeAreaInset: safeAreaInsets,
contentSafeAreaInset: contentSafeAreaInsets,
safeAreaInset,
contentSafeAreaInset,
viewportHeight,
viewportStableHeight,
viewportWidth,
viewportWidth: 0, // Not available in native API
isExpanded,
platform,
isMobile,
@@ -297,8 +189,7 @@ export function useTelegramSDK() {
expand,
disableVerticalSwipes,
enableVerticalSwipes,
// Expose raw SDK components for advanced usage
viewport: isReady ? viewport : null,
miniApp: isReady ? miniApp : null,
viewport: null,
miniApp: null,
};
}