react update
This commit is contained in:
parent
65a143ef4d
commit
6fbe286ca2
@ -1,8 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState, useCallback } from 'react';
|
||||||
import { isDemoMode, getDemoWebApp } from '../utils/demo';
|
|
||||||
import type { WebApp } from '@twa-dev/types';
|
import type { WebApp } from '@twa-dev/types';
|
||||||
|
import { isDemoMode, getDemoWebApp } from '../utils/demo';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -12,84 +12,68 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SafeWebApp = Partial<Pick<WebApp,
|
export interface UseTelegramWebAppResult {
|
||||||
| 'initData'
|
webApp: WebApp | null;
|
||||||
| 'initDataUnsafe'
|
error: Error | null;
|
||||||
| 'platform'
|
isLoading: boolean;
|
||||||
| 'colorScheme'
|
isInitialized: boolean;
|
||||||
| 'themeParams'
|
}
|
||||||
| 'isExpanded'
|
|
||||||
| 'viewportHeight'
|
|
||||||
| 'viewportStableHeight'
|
|
||||||
| 'headerColor'
|
|
||||||
| 'backgroundColor'
|
|
||||||
| 'isClosingConfirmationEnabled'
|
|
||||||
| 'BackButton'
|
|
||||||
| 'MainButton'
|
|
||||||
| 'ready'
|
|
||||||
| 'expand'
|
|
||||||
| 'close'
|
|
||||||
>>;
|
|
||||||
|
|
||||||
export function useTelegramWebApp() {
|
export function useTelegramWebApp(): UseTelegramWebAppResult {
|
||||||
const [webApp, setWebApp] = useState<SafeWebApp | null>(null);
|
const [webApp, setWebApp] = useState<WebApp | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<Error | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isInitialized, setIsInitialized] = useState(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const initWebApp = useCallback(async () => {
|
||||||
let isMounted = true;
|
|
||||||
|
|
||||||
const initWebApp = async () => {
|
|
||||||
try {
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
if (isDemoMode()) {
|
if (isDemoMode()) {
|
||||||
if (isMounted) {
|
|
||||||
const demoWebApp = getDemoWebApp();
|
const demoWebApp = getDemoWebApp();
|
||||||
setWebApp(demoWebApp);
|
setWebApp(demoWebApp);
|
||||||
setIsInitialized(true);
|
setIsInitialized(true);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
// Проверяем наличие Telegram WebApp в глобальном объекте
|
|
||||||
if (window.Telegram?.WebApp) {
|
if (window.Telegram?.WebApp) {
|
||||||
if (isMounted) {
|
setWebApp(window.Telegram.WebApp);
|
||||||
setWebApp(window.Telegram.WebApp as SafeWebApp);
|
|
||||||
setIsInitialized(true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Если WebApp не найден в глобальном объекте, пробуем импортировать SDK
|
|
||||||
const WebAppModule = await import('@twa-dev/sdk');
|
|
||||||
if (isMounted && WebAppModule.default) {
|
|
||||||
setWebApp(WebAppModule.default as SafeWebApp);
|
|
||||||
setIsInitialized(true);
|
setIsInitialized(true);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('WebApp не найден');
|
throw new Error('Telegram WebApp не найден');
|
||||||
}
|
|
||||||
} catch (importError) {
|
|
||||||
console.error('SDK import error:', importError);
|
|
||||||
throw new Error('Ошибка импорта Telegram Web App SDK');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('WebApp initialization error:', err);
|
console.error('Ошибка инициализации WebApp:', err);
|
||||||
if (isMounted) {
|
setError(err instanceof Error ? err : new Error('Неизвестная ошибка'));
|
||||||
setError('Ошибка инициализации Telegram Web App');
|
} finally {
|
||||||
}
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initWebApp();
|
||||||
|
}, [initWebApp]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!webApp) return;
|
||||||
|
|
||||||
|
const handleThemeChange = () => {
|
||||||
|
// Обновляем состояние при изменении темы
|
||||||
|
setWebApp(prevWebApp => {
|
||||||
|
if (!prevWebApp) return null;
|
||||||
|
return { ...prevWebApp };
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isInitialized) {
|
webApp.onEvent('themeChanged', handleThemeChange);
|
||||||
initWebApp();
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
isMounted = false;
|
webApp.offEvent('themeChanged', handleThemeChange);
|
||||||
};
|
};
|
||||||
}, [isInitialized]);
|
}, [webApp]);
|
||||||
|
|
||||||
return { webApp, error, isInitialized };
|
return { webApp, error, isLoading, isInitialized };
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { WebApp, WebAppUser, WebAppInitData, Platforms } from '@twa-dev/types';
|
import type { WebApp, WebAppUser, WebAppInitData, Platforms, HapticFeedback } from '@twa-dev/types';
|
||||||
|
|
||||||
// Демо данные для тестирования без Telegram
|
// Демо данные для тестирования без Telegram
|
||||||
const demoUser: WebAppUser = {
|
const demoUser: WebAppUser = {
|
||||||
@ -28,26 +28,14 @@ export const isDemoMode = () => {
|
|||||||
// Создаем заглушки для методов WebApp
|
// Создаем заглушки для методов WebApp
|
||||||
const createNoopFunction = () => () => {};
|
const createNoopFunction = () => () => {};
|
||||||
|
|
||||||
type SafeWebApp = Pick<WebApp,
|
// Создаем заглушку для HapticFeedback
|
||||||
| 'initData'
|
const demoHapticFeedback: HapticFeedback = {
|
||||||
| 'initDataUnsafe'
|
impactOccurred: (_style: "light" | "medium" | "heavy" | "rigid" | "soft") => demoHapticFeedback,
|
||||||
| 'platform'
|
notificationOccurred: (_type: "error" | "success" | "warning") => demoHapticFeedback,
|
||||||
| 'colorScheme'
|
selectionChanged: () => demoHapticFeedback
|
||||||
| 'themeParams'
|
};
|
||||||
| 'isExpanded'
|
|
||||||
| 'viewportHeight'
|
|
||||||
| 'viewportStableHeight'
|
|
||||||
| 'headerColor'
|
|
||||||
| 'backgroundColor'
|
|
||||||
| 'isClosingConfirmationEnabled'
|
|
||||||
| 'BackButton'
|
|
||||||
| 'MainButton'
|
|
||||||
| 'ready'
|
|
||||||
| 'expand'
|
|
||||||
| 'close'
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const getDemoWebApp = (): SafeWebApp => ({
|
export const getDemoWebApp = (): WebApp => ({
|
||||||
initData: JSON.stringify(demoInitData),
|
initData: JSON.stringify(demoInitData),
|
||||||
initDataUnsafe: demoInitData,
|
initDataUnsafe: demoInitData,
|
||||||
platform: 'WEBVIEW' as Platforms,
|
platform: 'WEBVIEW' as Platforms,
|
||||||
@ -92,6 +80,36 @@ export const getDemoWebApp = (): SafeWebApp => ({
|
|||||||
hideProgress: createNoopFunction(),
|
hideProgress: createNoopFunction(),
|
||||||
setParams: createNoopFunction()
|
setParams: createNoopFunction()
|
||||||
},
|
},
|
||||||
|
HapticFeedback: demoHapticFeedback,
|
||||||
|
CloudStorage: {
|
||||||
|
setItem: createNoopFunction(),
|
||||||
|
getItem: createNoopFunction(),
|
||||||
|
getItems: createNoopFunction(),
|
||||||
|
removeItem: createNoopFunction(),
|
||||||
|
removeItems: createNoopFunction(),
|
||||||
|
getKeys: createNoopFunction()
|
||||||
|
},
|
||||||
|
version: '7.0',
|
||||||
|
isVersionAtLeast: (version: string) => true,
|
||||||
|
setHeaderColor: createNoopFunction(),
|
||||||
|
setBackgroundColor: createNoopFunction(),
|
||||||
|
enableClosingConfirmation: createNoopFunction(),
|
||||||
|
disableClosingConfirmation: createNoopFunction(),
|
||||||
|
onEvent: createNoopFunction(),
|
||||||
|
offEvent: createNoopFunction(),
|
||||||
|
sendData: createNoopFunction(),
|
||||||
|
switchInlineQuery: createNoopFunction(),
|
||||||
|
openLink: createNoopFunction(),
|
||||||
|
openTelegramLink: createNoopFunction(),
|
||||||
|
openInvoice: createNoopFunction(),
|
||||||
|
showPopup: createNoopFunction(),
|
||||||
|
showAlert: createNoopFunction(),
|
||||||
|
showConfirm: createNoopFunction(),
|
||||||
|
showScanQrPopup: createNoopFunction(),
|
||||||
|
closeScanQrPopup: createNoopFunction(),
|
||||||
|
readTextFromClipboard: createNoopFunction(),
|
||||||
|
requestWriteAccess: createNoopFunction(),
|
||||||
|
requestContact: createNoopFunction(),
|
||||||
ready: createNoopFunction(),
|
ready: createNoopFunction(),
|
||||||
expand: createNoopFunction(),
|
expand: createNoopFunction(),
|
||||||
close: createNoopFunction(),
|
close: createNoopFunction(),
|
||||||
|
20
next.config.js
Normal file
20
next.config.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
swcMinify: true,
|
||||||
|
output: 'standalone',
|
||||||
|
experimental: {
|
||||||
|
serverActions: {
|
||||||
|
allowedOrigins: ['telegram.org', 't.me'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
webpack: (config) => {
|
||||||
|
config.externals.push({
|
||||||
|
'utf-8-validate': 'commonjs utf-8-validate',
|
||||||
|
'bufferutil': 'commonjs bufferutil',
|
||||||
|
});
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
31
package.json
31
package.json
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "campfire-id",
|
"name": "campfire-id",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
"description": "Telegram Mini App for user achievements and virtual economy",
|
"description": "Telegram Mini App for user achievements and virtual economy",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@ -9,30 +10,34 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.8.1",
|
"@chakra-ui/next-js": "^2.2.0",
|
||||||
"@emotion/react": "^11.11.1",
|
"@chakra-ui/react": "^2.8.2",
|
||||||
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@twa-dev/sdk": "^6.9.0",
|
"@twa-dev/sdk": "^7.0.0",
|
||||||
|
"@twa-dev/types": "^7.0.0",
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.6.7",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"framer-motion": "^10.16.4",
|
"framer-motion": "^11.0.8",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"mongoose": "^7.5.3",
|
"mongoose": "^8.2.1",
|
||||||
"next": "^13.5.4",
|
"next": "15.2.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.18",
|
"@types/express": "^4.17.18",
|
||||||
"@types/node": "^20.8.3",
|
"@types/node": "^20.11.24",
|
||||||
"@types/react": "^18.2.25",
|
"@types/react": "^18.2.61",
|
||||||
"eslint": "^8.51.0",
|
"@types/react-dom": "^18.2.19",
|
||||||
"eslint-config-next": "13.5.4",
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-config-next": "15.2.2",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user