From 8af9c21cb1503f56025af1bf19ebc852811068d6 Mon Sep 17 00:00:00 2001 From: degradin Date: Sun, 16 Mar 2025 12:35:18 +0300 Subject: [PATCH] add components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Безопасная работа с Telegram Web App SDK Улучшенная обработка ошибок Плавная загрузка с индикаторами Корректная работа в демо-режиме --- app/components/ClientOnly.tsx | 7 ++++++- app/components/MainApp.tsx | 35 ++++++++++++++++++++-------------- app/hooks/useTelegramWebApp.ts | 29 ++++++++++++++++++++++++++++ app/page.tsx | 6 ++++++ 4 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 app/hooks/useTelegramWebApp.ts diff --git a/app/components/ClientOnly.tsx b/app/components/ClientOnly.tsx index 6bf2620..cb0dd90 100644 --- a/app/components/ClientOnly.tsx +++ b/app/components/ClientOnly.tsx @@ -1,6 +1,7 @@ 'use client'; import { useEffect, useState } from 'react'; +import { Center, Spinner } from '@chakra-ui/react'; export default function ClientOnly({ children }: { children: React.ReactNode }) { const [hasMounted, setHasMounted] = useState(false); @@ -10,7 +11,11 @@ export default function ClientOnly({ children }: { children: React.ReactNode }) }, []); if (!hasMounted) { - return null; + return ( +
+ +
+ ); } return <>{children}; diff --git a/app/components/MainApp.tsx b/app/components/MainApp.tsx index 171457f..13e9d29 100644 --- a/app/components/MainApp.tsx +++ b/app/components/MainApp.tsx @@ -8,8 +8,7 @@ import TransferBalance from './TransferBalance'; import { auth, getProfile, getShopItems, purchaseItem, transferBalance } from '../utils/api'; import { IUser } from '../../backend/models/User'; import { IShopItem } from '../../backend/models/ShopItem'; -import { isDemoMode, getDemoWebApp } from '../utils/demo'; -import WebApp from '@twa-dev/sdk'; +import { useTelegramWebApp } from '../hooks/useTelegramWebApp'; type SafeUser = Omit; @@ -18,18 +17,20 @@ export default function MainApp() { const [user, setUser] = useState(null); const [shopItems, setShopItems] = useState([]); const toast = useToast(); + const { webApp, error: webAppError } = useTelegramWebApp(); + + useEffect(() => { + if (webApp) { + initApp(); + } + }, [webApp]); const initApp = async () => { try { setIsLoading(true); - - let webApp; - if (isDemoMode()) { - webApp = getDemoWebApp(); - } else if (typeof window !== 'undefined') { - webApp = WebApp; - } else { - throw new Error('Приложение должно быть открыто в браузере'); + + if (!webApp) { + throw new Error('Telegram Web App не инициализирован'); } // Авторизация пользователя @@ -58,11 +59,17 @@ export default function MainApp() { } }; - useEffect(() => { - initApp(); - }, []); + if (webAppError) { + return ( +
+ + {webAppError} + +
+ ); + } - if (isLoading) { + if (isLoading || !webApp) { return (
diff --git a/app/hooks/useTelegramWebApp.ts b/app/hooks/useTelegramWebApp.ts new file mode 100644 index 0000000..5da1dbb --- /dev/null +++ b/app/hooks/useTelegramWebApp.ts @@ -0,0 +1,29 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { isDemoMode, getDemoWebApp } from '../utils/demo'; + +export function useTelegramWebApp() { + const [webApp, setWebApp] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + const initWebApp = async () => { + try { + if (isDemoMode()) { + setWebApp(getDemoWebApp()); + } else if (typeof window !== 'undefined') { + const WebAppModule = await import('@twa-dev/sdk'); + setWebApp(WebAppModule.default); + } + } catch (err) { + setError('Ошибка инициализации Telegram Web App'); + console.error('WebApp initialization error:', err); + } + }; + + initWebApp(); + }, []); + + return { webApp, error }; +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 8d1240f..340ad81 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,8 +1,14 @@ import dynamic from 'next/dynamic'; +import { Center, Spinner } from '@chakra-ui/react'; import ClientOnly from './components/ClientOnly'; const MainApp = dynamic(() => import('./components/MainApp'), { ssr: false, + loading: () => ( +
+ +
+ ), }); export default function Home() {