Migrate to Telegram Navigator integration

Replace manual BackButton management with official @telegram-apps/react-router-integration
to fix navigation issues (back button cycling and double-click).

Changes:
- Migrate from @tma.js/sdk-react to @telegram-apps/sdk-react
- Downgrade react-router-dom to v6 for package compatibility
- Add AppWithNavigator component with Telegram navigator integration
- Use browser history mode (hashMode: null) to prevent hash URLs
- Add multi-level platform detection (user data, platform, version)
- Add try-catch error handling for navigator attach/detach
- Simplify useBackButton hook to no-op (navigator handles automatically)
- Update vite config with new Telegram packages

The navigator automatically manages BackButton based on router history,
falling back to BrowserRouter in regular browser environment.
This commit is contained in:
c0mrade
2026-02-04 07:18:43 +03:00
parent 482bdd0b0d
commit 483f3f4d0f
6 changed files with 268 additions and 180 deletions

243
package-lock.json generated
View File

@@ -24,7 +24,8 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-visually-hidden": "^1.2.4",
"@tanstack/react-query": "^5.8.0",
"@tma.js/sdk-react": "^3.0.15",
"@telegram-apps/react-router-integration": "^1.0.1",
"@telegram-apps/sdk-react": "^3.3.9",
"axios": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -37,7 +38,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.5.0",
"react-router-dom": "^7.13.0",
"react-router-dom": "^6.30.3",
"tailwind-merge": "^3.4.0",
"zustand": "^4.4.0"
},
@@ -2266,6 +2267,15 @@
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
"license": "MIT"
},
"node_modules/@remix-run/router": {
"version": "1.23.2",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
"integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.53",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
@@ -2607,47 +2617,60 @@
"react": "^18 || ^19"
}
},
"node_modules/@tma.js/bridge": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@tma.js/bridge/-/bridge-2.2.2.tgz",
"integrity": "sha512-dL7iZzYP/VC4/qJYSXPI1GXLGP3gLTp10L7iGY6PcjB2F4xXS2JnHUoYvD2DgQG1ogjE93zWnVIMN7inx1v+Eg==",
"node_modules/@telegram-apps/bridge": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/@telegram-apps/bridge/-/bridge-2.11.0.tgz",
"integrity": "sha512-kBZjWRRp/lxKeQ8r8cDWUY9EjxUtyeh/9xTQjsjuGRsCR5XTO1cyVbvcvqzHn53csGx3aBs+fOR3Pk3b6w2JHg==",
"deprecated": "This package is not supported anymore. Use @tma.js/bridge instead",
"license": "MIT",
"dependencies": {
"@tma.js/signals": "^1.0.1",
"@tma.js/toolkit": "^1.0.4",
"@tma.js/transformers": "^1.1.3",
"@tma.js/types": "^1.0.2",
"better-promises": "^1.0.0",
"error-kid": "^1.0.2",
"fp-ts": "^2.16.11",
"@telegram-apps/signals": "^1.1.2",
"@telegram-apps/toolkit": "^2.1.3",
"@telegram-apps/transformers": "^2.2.6",
"@telegram-apps/types": "^2.0.3",
"better-promises": "^0.4.1",
"error-kid": "^0.0.7",
"mitt": "^3.0.1",
"valibot": "^1.1.0"
"valibot": "1.0.0"
}
},
"node_modules/@tma.js/sdk": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/@tma.js/sdk/-/sdk-3.1.6.tgz",
"integrity": "sha512-NENkQa7G5N9kwbL20ErUMO9Fukxl9eVhcJ439PbCg2WYMk/x9oNbx2DhEzhX4xM718zSjYejmSj1oXCKk0PxYA==",
"node_modules/@telegram-apps/navigation": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/@telegram-apps/navigation/-/navigation-1.0.14.tgz",
"integrity": "sha512-bqNgF/J8Po7ZtsELm3E1a6aPr7awwxO3sIqD8J6u12urOlGoW5+1KxKKbkPa58mgXuQdsltd8apI+OVy0IYiUA==",
"license": "MIT"
},
"node_modules/@telegram-apps/react-router-integration": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@telegram-apps/react-router-integration/-/react-router-integration-1.0.1.tgz",
"integrity": "sha512-q5fC0ihXyUDqrSdLQ3u3gypmjI/rMU2mTHeAz9IU1F1bl5X+J17LxWmgLp+OlD0Y97bq2XYmc+UbKrYh+eN3Wg==",
"license": "MIT",
"dependencies": {
"@tma.js/bridge": "^2.2.2",
"@tma.js/signals": "^1.0.1",
"@tma.js/toolkit": "^1.0.4",
"@tma.js/transformers": "^1.1.3",
"@tma.js/types": "^1.0.2",
"better-promises": "^1.0.0",
"error-kid": "^1.0.2",
"fp-ts": "^2.16.11",
"valibot": "^1.1.0"
"peerDependencies": {
"@telegram-apps/sdk": "^1",
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-router-dom": "^6.22.3"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@tma.js/sdk-react": {
"version": "3.0.15",
"resolved": "https://registry.npmjs.org/@tma.js/sdk-react/-/sdk-react-3.0.15.tgz",
"integrity": "sha512-HsgqPINSBK87NIRZ+ZDol07QPhSQ3GOTofyZEH0xoaQjZWb9wVxUXwECa5ozRUdzWZI+Mgx8oD1pzrjyNkDjFA==",
"node_modules/@telegram-apps/sdk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@telegram-apps/sdk/-/sdk-1.1.3.tgz",
"integrity": "sha512-gvcXNttbCouDNTxjDUbO5FS/BdaHYO0ibSddQxiYitShPIDZDxGon0Eh3OSsgUIVPSQSNdXqkXaeqYgA+jeY0A==",
"license": "MIT",
"peer": true
},
"node_modules/@telegram-apps/sdk-react": {
"version": "3.3.9",
"resolved": "https://registry.npmjs.org/@telegram-apps/sdk-react/-/sdk-react-3.3.9.tgz",
"integrity": "sha512-85jF1ICT8sYCNzXu19SqJrfrS8XslsvV14KUcToiyL7H5ZMXHt0JQKM+QJgULjnLjEswweQ4/7Bd7mNULf/BIg==",
"license": "MIT",
"dependencies": {
"@tma.js/sdk": "^3.1.6"
"@telegram-apps/sdk": "^3.11.8"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
@@ -2659,38 +2682,66 @@
}
}
},
"node_modules/@tma.js/signals": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@tma.js/signals/-/signals-1.0.1.tgz",
"integrity": "sha512-i2HUuwGqL4BmM5KAklAUhMhlEgUOF+F4nMHHS/zxrmD0upHE/0CiXCEdQxVeeOGN6e2RrKlonA40sDtR6OUDCw==",
"node_modules/@telegram-apps/sdk-react/node_modules/@telegram-apps/sdk": {
"version": "3.11.8",
"resolved": "https://registry.npmjs.org/@telegram-apps/sdk/-/sdk-3.11.8.tgz",
"integrity": "sha512-vlpkYzMJCV9Cadsn9Q+/hbHNR39j5o96N9z4CjZ6AFHkkxOeOqVRrq9zRBw0gmffROkF2bU0WQxhRj8KZ/bPhw==",
"license": "MIT",
"dependencies": {
"@telegram-apps/bridge": "^2.11.0",
"@telegram-apps/navigation": "^1.0.14",
"@telegram-apps/signals": "^1.1.2",
"@telegram-apps/toolkit": "^2.1.3",
"@telegram-apps/transformers": "^2.2.6",
"@telegram-apps/types": "^2.0.3",
"better-promises": "^0.4.1",
"error-kid": "^0.0.7",
"valibot": "1.0.0"
}
},
"node_modules/@telegram-apps/signals": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@telegram-apps/signals/-/signals-1.1.2.tgz",
"integrity": "sha512-1P1kdCLX7MfETGPxH7f3UZKIsdE7Tz5S7QmN4Km1sbYQMakD5Bi1NecSMR7/wnHp50gWMI1JzENcMtCEmouhSg==",
"license": "MIT"
},
"node_modules/@tma.js/toolkit": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tma.js/toolkit/-/toolkit-1.0.4.tgz",
"integrity": "sha512-6CDlkgc+43WD2jy6jog3B50yt9t+/wRwrN25zOa4iSw4IzfqoFjaQcJzTupBYaRxz19C3Rrir7p0/qStS/Z8vw==",
"node_modules/@telegram-apps/toolkit": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@telegram-apps/toolkit/-/toolkit-2.1.3.tgz",
"integrity": "sha512-LPUBL7hxQTOr+Dowyk9a1O82nQS4ja4+OYiYWtvqq5nNUHC6Gbbus0zGWCbFcj9CLnIzaeb5HWOg5iSnhoRcyg==",
"license": "MIT"
},
"node_modules/@telegram-apps/transformers": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/@telegram-apps/transformers/-/transformers-2.2.6.tgz",
"integrity": "sha512-MMBRs3demeBT9Cd614KKZmak7eEyNdEbfu99a0SwEEJe2oIODjJLrUxrhUcAOc5wvTRfrKka27VXVgruauLhdg==",
"deprecated": "This package is not supported anymore. Use @tma.js/transfomers instead",
"license": "MIT",
"dependencies": {
"better-promises": "^1.0.0",
"fp-ts": "^2.16.11"
"@telegram-apps/toolkit": "^2.1.3",
"@telegram-apps/types": "^2.0.3",
"valibot": "1.0.0-beta.14"
}
},
"node_modules/@tma.js/transformers": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@tma.js/transformers/-/transformers-1.1.3.tgz",
"integrity": "sha512-zRL+fdo/NBpGqCJfl8ItAvcJIFT5Zy6UOYJwQPmUV5/gTHgmSvmGlrP43PeVi9XZ7Ggf4xbO6LUa4ehxozhMTA==",
"node_modules/@telegram-apps/transformers/node_modules/valibot": {
"version": "1.0.0-beta.14",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0-beta.14.tgz",
"integrity": "sha512-tLyV2rE5QL6U29MFy3xt4AqMrn+/HErcp2ZThASnQvPMwfSozjV1uBGKIGiegtZIGjinJqn0SlBdannf18wENA==",
"license": "MIT",
"dependencies": {
"@tma.js/toolkit": "^1.0.4",
"@tma.js/types": "^1.0.2",
"fp-ts": "^2.16.11",
"valibot": "^1.1.0"
"peerDependencies": {
"typescript": ">=5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@tma.js/types": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@tma.js/types/-/types-1.0.2.tgz",
"integrity": "sha512-qs4mi+U1xZmMQBdMhWAo1X4YqUJ/ae0y28s+GNCpQq58bsJo0h8rvyVOB1RwPvXogIY9+yribbZe6z3AIJmsAQ==",
"node_modules/@telegram-apps/types": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@telegram-apps/types/-/types-2.0.3.tgz",
"integrity": "sha512-pXh9BdnLZF3e2BGc4WL+RTRMAUpqKpaSP3Rs8rB4WyRwIoRSGWFKE4gtT/9m42LGixB8YVwdo/pJ+9XO765XEA==",
"deprecated": "This package is not supported anymore. Use @tma.js/types instead",
"license": "MIT"
},
"node_modules/@types/babel__core": {
@@ -3282,12 +3333,12 @@
}
},
"node_modules/better-promises": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/better-promises/-/better-promises-1.0.0.tgz",
"integrity": "sha512-gPgL2nRgeSbMIe3QpsYdKR3K0S9OZuphVuos60Eqsw8d/6GivOkyJ5D/zmnolJ6hzh7upnnflBUWUlQh4qpU2A==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/better-promises/-/better-promises-0.4.1.tgz",
"integrity": "sha512-cDW7eMvhvCoWzSih5o/OxsAgTUfP05yGMq77xNZUTmcZoNU9vEeFZJ+yJJi4lnocvxFrVFKsG0Yxt7ZnuYJEig==",
"license": "MIT",
"dependencies": {
"error-kid": "^1.0.1"
"error-kid": "^0.0.7"
}
},
"node_modules/binary-extensions": {
@@ -3604,19 +3655,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/cookie": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3757,9 +3795,9 @@
}
},
"node_modules/error-kid": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/error-kid/-/error-kid-1.0.2.tgz",
"integrity": "sha512-Xvq0ZrY/azCbREWKt9E/3mXDF0MkuEVVvHnOKutUhtq2O8pyneEixQ4nSFkA19Xfn+/OVSg//iVG0dxIDj7DIA==",
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/error-kid/-/error-kid-0.0.7.tgz",
"integrity": "sha512-8mFs7ZaDWlBFgjOy4lHLMCe2+KZfZXGx5GOgh2VQ/M1CCIvSWzbl2OMl+5fdZgrgoUfhTeF+NPhmqfEvUhN8yw==",
"license": "MIT"
},
"node_modules/es-define-property": {
@@ -4241,12 +4279,6 @@
"node": ">= 6"
}
},
"node_modules/fp-ts": {
"version": "2.16.11",
"resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.11.tgz",
"integrity": "sha512-LaI+KaX2NFkfn1ZGHoKCmcfv7yrZsC3b8NtWsTVQeHkq4F27vI5igUuO53sxqDEa2gNQMHFPmpojDw/1zmUK7w==",
"license": "MIT"
},
"node_modules/fraction.js": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
@@ -5679,41 +5711,36 @@
}
},
"node_modules/react-router": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz",
"integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==",
"version": "6.30.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
"integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0"
"@remix-run/router": "1.23.2"
},
"engines": {
"node": ">=20.0.0"
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz",
"integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==",
"version": "6.30.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
"integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
"license": "MIT",
"peer": true,
"dependencies": {
"react-router": "7.13.0"
"@remix-run/router": "1.23.2",
"react-router": "6.30.3"
},
"engines": {
"node": ">=20.0.0"
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/react-style-singleton": {
@@ -5915,12 +5942,6 @@
"node": ">=10"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -6414,9 +6435,9 @@
"license": "MIT"
},
"node_modules/valibot": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz",
"integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz",
"integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==",
"license": "MIT",
"peerDependencies": {
"typescript": ">=5"

View File

@@ -32,7 +32,8 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-visually-hidden": "^1.2.4",
"@tanstack/react-query": "^5.8.0",
"@tma.js/sdk-react": "^3.0.15",
"@telegram-apps/react-router-integration": "^1.0.1",
"@telegram-apps/sdk-react": "^3.3.9",
"axios": "^1.6.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -45,7 +46,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.5.0",
"react-router-dom": "^7.13.0",
"react-router-dom": "^6.30.3",
"tailwind-merge": "^3.4.0",
"zustand": "^4.4.0"
},

102
src/AppWithNavigator.tsx Normal file
View File

@@ -0,0 +1,102 @@
import { useEffect, useMemo } from 'react';
import { BrowserRouter, Router } from 'react-router-dom';
import { useIntegration } from '@telegram-apps/react-router-integration';
import { initNavigator } from '@telegram-apps/sdk';
import App from './App';
import { PlatformProvider } from './platform/PlatformProvider';
import { ThemeColorsProvider } from './providers/ThemeColorsProvider';
import { WebSocketProvider } from './providers/WebSocketProvider';
import { ToastProvider } from './components/Toast';
import { TooltipProvider } from './components/primitives/Tooltip';
/**
* Check if running inside Telegram Mini App
* Uses multiple checks to reliably detect Telegram environment
*/
function isTelegramMiniApp(): boolean {
if (typeof window === 'undefined') return false;
const webApp = window.Telegram?.WebApp;
if (!webApp) return false;
// Check 1: initDataUnsafe should have user data in real Telegram
const hasUserData = webApp.initDataUnsafe?.user?.id !== undefined;
// Check 2: Platform should not be 'unknown' (which is default in browser)
const validPlatform = webApp.platform !== 'unknown' && webApp.platform !== '';
// Check 3: Version should be present (SDK loads in Telegram only)
const hasVersion = webApp.version !== undefined && webApp.version !== '';
return hasUserData || (validPlatform && hasVersion);
}
/**
* Component wrapper for Telegram navigator setup.
* Integrates Telegram Mini Apps navigator with React Router to provide
* automatic BackButton management based on navigation history.
* Falls back to BrowserRouter when not in Telegram Mini App.
*/
/**
* Navigator-based router for Telegram Mini App
*/
function TelegramRouter({ children }: { children: React.ReactNode }) {
const navigator = useMemo(() => initNavigator('app-navigation-state', { hashMode: null }), []);
const [location, reactNavigator] = useIntegration(navigator);
useEffect(() => {
try {
navigator.attach();
return () => {
try {
navigator.detach();
} catch (err) {
console.warn('Failed to detach navigator:', err);
}
};
} catch (err) {
console.warn('Failed to attach navigator:', err);
}
}, [navigator]);
return (
<Router location={location} navigator={reactNavigator}>
{children}
</Router>
);
}
export function AppWithNavigator() {
const isTelegram = useMemo(() => {
const result = isTelegramMiniApp();
console.log('[AppWithNavigator] Platform detection:', {
isTelegram: result,
platform: window.Telegram?.WebApp?.platform,
hasUser: window.Telegram?.WebApp?.initDataUnsafe?.user?.id !== undefined,
version: window.Telegram?.WebApp?.version,
});
return result;
}, []);
// Common app content
const appContent = (
<PlatformProvider>
<ThemeColorsProvider>
<TooltipProvider>
<ToastProvider>
<WebSocketProvider>
<App />
</WebSocketProvider>
</ToastProvider>
</TooltipProvider>
</ThemeColorsProvider>
</PlatformProvider>
);
// Use Telegram navigator in Mini App, BrowserRouter elsewhere
if (isTelegram) {
return <TelegramRouter>{appContent}</TelegramRouter>;
}
return <BrowserRouter>{appContent}</BrowserRouter>;
}

View File

@@ -1,13 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
import { PlatformProvider } from './platform/PlatformProvider';
import { ThemeColorsProvider } from './providers/ThemeColorsProvider';
import { WebSocketProvider } from './providers/WebSocketProvider';
import { ToastProvider } from './components/Toast';
import { TooltipProvider } from './components/primitives/Tooltip';
import { AppWithNavigator } from './AppWithNavigator';
import { initLogoPreload } from './api/branding';
import { initTelegramSDK } from './hooks/useTelegramSDK';
import './i18n';
@@ -31,19 +25,7 @@ const queryClient = new QueryClient({
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<PlatformProvider>
<ThemeColorsProvider>
<TooltipProvider>
<ToastProvider>
<WebSocketProvider>
<App />
</WebSocketProvider>
</ToastProvider>
</TooltipProvider>
</ThemeColorsProvider>
</PlatformProvider>
</BrowserRouter>
<AppWithNavigator />
</QueryClientProvider>
</React.StrictMode>,
);

View File

@@ -1,6 +1,3 @@
import { useEffect, useRef, useCallback } from 'react';
import { usePlatform } from '@/platform/hooks/usePlatform';
interface UseBackButtonOptions {
/**
* Whether the back button should be visible
@@ -11,65 +8,46 @@ interface UseBackButtonOptions {
/**
* Hook to manage the Telegram BackButton
* Automatically shows/hides based on component lifecycle
*
* @param onBack - Callback when back button is pressed
* @param options - Configuration options
* NOTE: This hook is now a no-op for backward compatibility.
* The Telegram Navigator (@telegram-apps/react-router-integration) handles
* BackButton visibility and navigation automatically based on router history.
*
* The navigator:
* - Shows BackButton when there's navigation history
* - Hides BackButton on root page
* - Handles back button clicks automatically
*
* @param onBack - (Ignored) Callback when back button is pressed
* @param options - (Ignored) Configuration options
*
* @example
* ```tsx
* function MyPage() {
* const navigate = useNavigate();
* useBackButton(() => navigate(-1));
* useBackButton(() => navigate('/admin')); // No-op: navigator handles this
* // ...
* }
* ```
*/
export function useBackButton(
onBack: (() => void) | null | undefined,
options: UseBackButtonOptions = {},
_onBack: (() => void) | null | undefined,
_options: UseBackButtonOptions = {},
): void {
const { backButton, capabilities } = usePlatform();
const { visible = true } = options;
// Use ref to prevent callback recreation issues
const callbackRef = useRef(onBack);
callbackRef.current = onBack;
// Stable callback wrapper
const handleBack = useCallback(() => {
callbackRef.current?.();
}, []);
useEffect(() => {
// If no native back button support, do nothing
if (!capabilities.hasBackButton) {
return;
}
// If callback is null/undefined or visible is false, hide button
if (!onBack || !visible) {
backButton.hide();
return;
}
// Show the back button with our handler
backButton.show(handleBack);
// Cleanup: hide button when component unmounts
return () => {
backButton.hide();
};
}, [backButton, capabilities.hasBackButton, handleBack, onBack, visible]);
// No-op: Navigator handles BackButton automatically
return;
}
/**
* Hook to conditionally show back button based on navigation depth
* Useful for showing back button only when there's history to go back to
*
* @param canGoBack - Whether navigation back is possible
* @param onBack - Callback when back button is pressed
* NOTE: This hook is now a no-op for backward compatibility.
* The navigator handles conditional visibility automatically.
*
* @param canGoBack - (Ignored) Whether navigation back is possible
* @param onBack - (Ignored) Callback when back button is pressed
*/
export function useConditionalBackButton(canGoBack: boolean, onBack: () => void): void {
useBackButton(canGoBack ? onBack : null);
export function useConditionalBackButton(_canGoBack: boolean, _onBack: () => void): void {
// No-op: Navigator handles BackButton automatically
return;
}

View File

@@ -49,7 +49,11 @@ export default defineConfig({
'@radix-ui/react-visually-hidden',
],
'vendor-dnd': ['@dnd-kit/core', '@dnd-kit/sortable', '@dnd-kit/utilities'],
'vendor-telegram': ['@tma.js/sdk-react'],
'vendor-telegram': [
'@telegram-apps/sdk',
'@telegram-apps/sdk-react',
'@telegram-apps/react-router-integration',
],
'vendor-utils': [
'axios',
'zustand',