// hooks/useTelegramWebApp.ts // Hook для интеграции с Telegram WebApp API import { useEffect, useState } from 'react'; declare global { interface Window { Telegram?: { WebApp: { ready: () => void; expand: () => void; close: () => void; isExpanded: boolean; viewportHeight: number; viewportStableHeight: number; headerColor: string; backgroundColor: string; isClosingConfirmationEnabled: boolean; platform: string; version: string; MainButton: { text: string; color: string; textColor: string; isVisible: boolean; isActive: boolean; isProgressVisible: boolean; setText: (text: string) => void; onClick: (callback: () => void) => void; offClick: (callback: () => void) => void; show: () => void; hide: () => void; enable: () => void; disable: () => void; showProgress: (leaveActive?: boolean) => void; hideProgress: () => void; setParams: (params: { text?: string; color?: string; text_color?: string; is_active?: boolean; is_visible?: boolean }) => void; }; BackButton: { isVisible: boolean; onClick: (callback: () => void) => void; offClick: (callback: () => void) => void; show: () => void; hide: () => void; }; HapticFeedback: { impactOccurred: (style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft') => void; notificationOccurred: (type: 'error' | 'success' | 'warning') => void; selectionChanged: () => void; }; setHeaderColor: (color: string) => void; setBackgroundColor: (color: string) => void; enableClosingConfirmation: () => void; disableClosingConfirmation: () => void; showPopup: (params: { title?: string; message: string; buttons: Array<{ id?: string; type: string; text?: string }>; }, callback?: (buttonId: string) => void) => void; showAlert: (message: string, callback?: () => void) => void; showConfirm: (message: string, callback?: (confirmed: boolean) => void) => void; openLink: (url: string, options?: { try_instant_view?: boolean }) => void; openTelegramLink: (url: string) => void; openInvoice: (url: string, callback?: (status: string) => void) => void; shareToStory: (media_url: string, params?: { text?: string; widget_link?: { url: string; name?: string; }; }) => void; switchInlineQuery: (query: string, choose_chat_types?: string[]) => void; sendData: (data: string) => void; initData: string; initDataUnsafe: { query_id?: string; user?: { id: number; first_name: string; last_name?: string; username?: string; language_code?: string; is_premium?: boolean; photo_url?: string; }; receiver?: { id: number; first_name: string; last_name?: string; username?: string; language_code?: string; is_premium?: boolean; }; chat?: { id: number; type: string; title: string; username?: string; photo_url?: string; }; chat_type?: string; chat_instance?: string; start_param?: string; can_send_after?: number; auth_date: number; hash: string; }; themeParams: { bg_color?: string; text_color?: string; hint_color?: string; link_color?: string; button_color?: string; button_text_color?: string; secondary_bg_color?: string; header_bg_color?: string; accent_text_color?: string; section_bg_color?: string; section_header_text_color?: string; subtitle_text_color?: string; destructive_text_color?: string; }; colorScheme: 'light' | 'dark'; isVersionAtLeast: (version: string) => boolean; onEvent: (eventType: string, eventHandler: () => void) => void; offEvent: (eventType: string, eventHandler: () => void) => void; }; }; } } export function useTelegramWebApp() { const [webApp, setWebApp] = useState(null); const [isReady, setIsReady] = useState(false); useEffect(() => { // Проверяем доступность Telegram WebApp только на клиенте if (typeof window === 'undefined') return; const tg = window.Telegram?.WebApp; if (!tg) { console.warn('[TelegramWebApp] Not running in Telegram'); setIsReady(true); // Всё равно помечаем как ready для dev return; } console.log('[TelegramWebApp] Initializing...', { platform: tg.platform, version: tg.version, colorScheme: tg.colorScheme, user: tg.initDataUnsafe.user, }); // Инициализация Telegram WebApp tg.ready(); tg.expand(); // Настройка темы tg.setHeaderColor('bg_color'); tg.setBackgroundColor('#18222d'); // Отключить подтверждение закрытия (можно включить при необходимости) tg.disableClosingConfirmation(); setWebApp(tg); setIsReady(true); // Cleanup return () => { tg.MainButton.hide(); tg.BackButton.hide(); }; }, []); return { webApp, isReady, isTelegram: !!webApp, user: webApp?.initDataUnsafe.user, platform: webApp?.platform, colorScheme: webApp?.colorScheme, themeParams: webApp?.themeParams, }; } // Helper функции для удобства export function useTelegramMainButton( text: string, onClick: () => void, options?: { color?: string; textColor?: string; enabled?: boolean; } ) { const { webApp } = useTelegramWebApp(); useEffect(() => { if (!webApp) return; webApp.MainButton.setText(text); webApp.MainButton.onClick(onClick); if (options?.color) { webApp.MainButton.color = options.color; } if (options?.textColor) { webApp.MainButton.textColor = options.textColor; } if (options?.enabled !== undefined) { if (options.enabled) { webApp.MainButton.enable(); } else { webApp.MainButton.disable(); } } webApp.MainButton.show(); return () => { webApp.MainButton.offClick(onClick); webApp.MainButton.hide(); }; }, [webApp, text, onClick, options]); } export function useTelegramBackButton(onClick: () => void) { const { webApp } = useTelegramWebApp(); useEffect(() => { if (!webApp) return; webApp.BackButton.onClick(onClick); webApp.BackButton.show(); return () => { webApp.BackButton.offClick(onClick); webApp.BackButton.hide(); }; }, [webApp, onClick]); } export function useTelegramHaptic() { const { webApp } = useTelegramWebApp(); return { impact: (style: 'light' | 'medium' | 'heavy' | 'rigid' | 'soft' = 'medium') => { webApp?.HapticFeedback.impactOccurred(style); }, notification: (type: 'error' | 'success' | 'warning') => { webApp?.HapticFeedback.notificationOccurred(type); }, selection: () => { webApp?.HapticFeedback.selectionChanged(); }, }; }