Files
app_umbrix/hooks/useTelegramWebApp.ts

274 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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<typeof window.Telegram.WebApp | null>(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();
},
};
}