Регрессия после a62d689: Back прятался только при deep-link входе
(depthRef === 0). При внутреннем переходе на /subscriptions/:id (depth > 0)
показывался Back, а в single-tariff «назад» уходил в /subscriptions, который
тут же редиректит обратно на деталь (Subscriptions.tsx) — петля, и юзер видел
Back вместо Close.
Решение depth-независимое: если список-редирект всё равно отбрасывает на эту
же страницу (single-tariff, ≤1 подписки = listRedirectsToDetail, инверсия
listIsSafe из обработчика), деталь — это верхний экран. Прячем Back всегда,
Telegram показывает нативный Close. Петля невозможна по построению: без кнопки
Back обработчик navigate(-1) в редиректящий список просто не вызвать.
Multi-tariff и >1 подписки сохраняют реальный Back к осмысленному списку.
На iOS Telegram кнопка «Назад» на /subscriptions/:id казалась мёртвой:
fallback вёл на /subscriptions, который авто-редиректит обратно на деталь
(single-tariff, 1 подписка) — молчаливая петля. Причина — ненадёжный
window.history.state.idx, который мутируют собственные redirect'ы.
idx заменён на надёжный счётчик глубины по useNavigationType (PUSH +1,
POP −1, REPLACE без изменений, дедуп по location.key). Кнопка корректно
показывается/прячется, navigate(-1) берётся только при реальной истории.
Плюс fail-closed fallback: с детали уходим в '/' если список не доказанно
безопасен (multi-tariff или >1 подписки) — петля невозможна.
GitHub-issue #436.
Refines 3c2f650 — that commit broke the loop by suppressing the single-tariff
redirect on idx=0, but left the BackButton visible. The user still saw Back
on the detail page and needed two taps (Back → Close) to exit. Серёжа's
report was specifically that Back should not appear at all when you land on
your only subscription via a bot button.
Move the decision up to TelegramBackButton:
- Subscribe to the existing ['subscriptions-list'] query (deduped by
React Query, so no extra fetch).
- On /subscriptions/:id, when multi_tariff_enabled is false and there is
no in-app history (idx=0 deep-link entry), hide the BackButton. Telegram
then surfaces its native Close (X) in the header.
- Multi-tariff users still see BackButton on /subscriptions/:id deep-links
because their /subscriptions list is meaningful (they have many subs).
The 2bcba3b fallback-to-parent behaviour remains intact for unrelated
deep-links like /balance/top-up, /admin/*, etc.
Revert the defensive guard in Subscriptions.tsx — the loop can no longer be
triggered because no BackButton is shown to trigger it.
Behaviour summary:
flow BackButton exit cost
-------------------------------------- ---------- ---------
deep-link → /subscriptions/:id (1T) hidden Close, 1 tap
/ → /subscriptions → /subscriptions/:id shown Back → /, 1 tap
deep-link → /balance/top-up shown Back → /balance ✓
deep-link → /subscriptions/:id (multi) shown Back → /subscriptions list
Reported by Серёжа, bugs topic #599679.
Bot deep-links open the Mini App directly on nested routes (/admin,
/balance/top-up, /info, /profile, ...) where React Router history has a
single entry, so navigate(-1) was a no-op and the native back button
looked dead. Fall back to the derived parent route when there is no
in-app history (window.history.state.idx === 0).
- Fix stale initData comparison in clearStaleSessionIfNeeded that destroyed
valid refresh tokens on mobile WebView reopens
- Restrict X-Telegram-Init-Data header to auth endpoints only
- Close Mini App on auth retry to force fresh initData from Telegram
- Merge Connection page error/not-configured states for better UX
- Remove unnecessary comments across 40+ files (section dividers,
restating comments, noise catch block comments)
- Configure ESLint allowEmptyCatch to properly handle intentional
empty catch blocks (62 warnings resolved)
Prevent MutationObserver re-initialization on every render by moving
the options object out of JSX (was creating a new object reference
on each render of AppWithNavigator).
Back button was showing on all non-root routes including top-level
pages reachable from the bottom navigation menu (subscription, balance,
referral, support, wheel). These pages don't need a back button since
users navigate between them via the bottom tab bar.
- Обернуть каждый mount-вызов в safeMountSync() для защиты от
ConcurrentCallError при HMR/повторной инициализации
- Перенести requestFullscreen() внутрь mountViewport().then() — fullscreen
требует смонтированный viewport, ранее вызывался через dynamic import
с setTimeout до завершения mount
- Стабилизировать обработчик BackButton через useRef + useCallback —
navigate меняется каждый рендер, что вызывало постоянную
пере-подписку и потерю обработчика
Полный переход с нативного window.Telegram.WebApp API на @telegram-apps/sdk-react v3.
Bridge SDK оборачивал receiveEvent, из-за чего popup_closed не доходил до нативного
обработчика — это было основной причиной бага с двойным открытием попапа.
Изменения:
- Удалён @telegram-apps/react-router-integration (привязан к SDK v1)
- Инициализация SDK v3 в main.tsx: init(), restoreInitData(), mount всех компонентов
- AppWithNavigator: убран TelegramRouter (initNavigator + useIntegration), все платформы
на BrowserRouter, добавлен TelegramBackButton через SDK v3
- useTelegramSDK: детекция через retrieveLaunchParams(), реактивные значения через
useSignal() (fullscreen, viewport, safe area insets), initData через retrieveRawInitData()
- TelegramAdapter: полная перезапись — попапы через showPopup() (Promise-based, без
ручного onEvent/offEvent/timeout), кнопки через setMainButtonParams/showBackButton,
haptic через hapticFeedbackImpactOccurred, тема через themeParamsState с конвертацией
camelCase→snake_case, cloud storage через getCloudStorageItem/setCloudStorageItem
- api/client.ts: initData через retrieveRawInitData() вместо window.Telegram.WebApp.initData
- AppHeader: фото пользователя через initDataUser() сигнал
- ConnectionModal: openLink через SDK вместо window.Telegram.WebApp.openLink
- ColorPicker: детекция Telegram через isInTelegramWebApp()
- Удалён интерфейс TelegramWebApp (368 строк) и Window augmentation из vite-env.d.ts
- Убрано поле telegram из PlatformContext в types.ts
- Обновлён manualChunks в vite.config.ts
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.