- Кнопка «Подключить устройство» заблокирована при достижении лимита
- Haptic feedback при нажатии на заблокированную кнопку
- Предупреждение «Отключите устройства для подключения новых»
- Убран дублирующийся текст трафика под прогресс-баром (безлимит)
- Replace setInterval with recursive setTimeout to prevent overlapping async polls
- Add cancellation flag in auto-start effect for React Strict Mode double-mount
- Use isAxiosError() instead of unsafe type assertion
- Remove consumeCampaignSlug/consumeReferralCode from loginWithDeepLink (fired on every poll tick, destroying values after first 202)
- Clear previous interval/timeout before starting new deep link auth
- Store expire timeout in ref for cleanup on unmount
- Use server expires_in instead of hardcoded 5 minutes
- Show error message when token expires (not just clear state)
- Add consumeCampaignSlug/consumeReferralCode to loginWithDeepLink
Добавлен fallback через бота когда виджет Telegram не загружается:
- Таймаут 8 сек на загрузку скрипта (OIDC + legacy)
- Автоматический переход на deep link auth
- Polling каждые 2.5 сек до подтверждения в боте
- ConnectedAccounts: таймаут + сообщение при недоступности
- Переводы: ru, en, zh, fa
- Add varsIgnorePattern to no-unused-vars for destructuring patterns
- Fix all react-hooks/exhaustive-deps by adding missing dependencies
- Refactor useAnimatedNumber to use ref instead of stale state closure
- Wrap handleLinkResult in useCallback for stable deps
- Extract OAuth utilities from OAuthCallback.tsx to utils/oauth.ts
- Extract background config utilities to utils/backgroundConfig.ts
- Remove unused catch parameter in GiftSubscription
- 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)
- Add is_limited to Subscription type
- Show yellow traffic-exhausted badge on Subscription and AdminUsers pages
- SubscriptionCardExpired: amber theme with warning icon and buy-traffic CTA for limited
- Dashboard: route limited subscriptions to SubscriptionCardExpired
- Subscription page: show additional options (buy traffic) for limited subs
- Use is_limited boolean instead of status string comparison
- Add trafficLimited translations for ru, en, zh, fa
- AdminUserDetail StatusBadge: add limited yellow styling
Icons enlarged to 18px, padding increased. On hover each button
smoothly expands to reveal its label with opacity and max-width
transition (200ms). Uses group/group-hover pattern.
Text labels overflow even at 2xl with Russian + 9 items.
Switch to icon-only mode at all desktop widths. Labels kept
as sr-only for accessibility, title attribute provides tooltips.
Remove horizontal scroll from desktop top nav bar. Items now show
icons only at 1024-1279px with native tooltips, and icons+labels
at 1280px+. All 9 items fit on screen in any language without
scrolling.
PendingGiftCard was linking to /buy/success/:token which uses the landing
API (exact token match). Since gift tokens are now truncated to 12 chars
in API responses, this caused 404s. Route to /gift?tab=activate&code=
which uses the gift API with prefix-based lookup.
- Expired daily tariffs now call purchaseTariff(tariff_id, 1) for 1-day purchase
- Balance check uses daily_price_kopeks for daily tariffs instead of 100 kopeks minimum
- Disabled daily tariffs still use togglePause for resume
- Add menuLayout.ts API client with normalizeConfig and type definitions
- Add MenuEditorTab.tsx with DnD rows, button CRUD, style/emoji/label editors
- Replace ButtonsTab with MenuEditorTab on admin settings page
- Add menu editor translations for ru, en, zh, fa locales
- Loading/error states, useMemo optimizations, proper ref patterns
WATA DDoS Guard blocks requests without Referer (403 error).
Removed noreferrer from window.open and <a> tags on payment URLs.
noopener alone is sufficient for security (prevents window.opener access).
Add CABINET_GIFT_ENABLED toggle in Admin Settings > Branding > Interface Options,
alongside existing fullscreen and email auth toggles. Includes updateGiftEnabled
API method and i18n keys for all 4 locales (ru/en/zh/fa).
- Handle expired status in GiftResult (stop polling + show FailedState)
- Add PollErrorState for balance mode poll errors (softer UX)
- Remove non-null assertions in handleSubmit (explicit narrowing)
- Wrap gift routes in ErrorBoundary
- Add pollErrorTitle/pollErrorDesc i18n keys to all 4 locales
Replace toast-based payment return with animated result page showing
pending/success/failed/timeout states. Extract shared Spinner,
AnimatedCheckmark and AnimatedCrossmark components. Add sessionStorage
persistence with validation and TTL for cross-redirect payment data.
Unify ProtectedRoute with withLayout prop, add aria-live accessibility.
- Show SubscriptionCardExpired for disabled daily subscriptions
- Use togglePause() API for resume instead of renewSubscription()
- Add "Suspended" status badge and balance query invalidation
- Add dashboard.suspended and subscription.pause.suspended translations (ru, en, zh, fa)
- WebSocketNotifications: invalidate purchase-options on all 10 balance-affecting events
- Dashboard: invalidate purchase-options after trial activation
- Balance: invalidate purchase-options after payment return and promocode activation
- PromoOffersSection: invalidate purchase-options and balance after promo claim
- Wrap /connection/qr route in ProtectedRoute with Layout
- Remove fullscreen overlay and custom close button
- Add AdminBackButton with replace prop to avoid history cycles
- Use replace navigation from Connection to QR page
- Add replace prop support to AdminBackButton component
Telegram deprecated the data-auth-url redirect flow, which returns a
blank page with "deprecated" text. Switch both TelegramLinkWidget
(account linking) and TelegramLoginButton (legacy login) to use
data-onauth callback approach that works client-side without redirects.
Extract BackgroundConfigEditor as reusable controlled component from
BackgroundEditor. Add background settings section to landing editor.
Render per-landing backgrounds on public purchase pages.
- Extract BackgroundConfigEditor (value/onChange) from BackgroundEditor
- Refactor BackgroundEditor to thin wrapper with API persistence
- Add StaticBackgroundRenderer for prop-based config (public pages)
- Add background_config to landing API types and editor form
- Render animated background on QuickPurchase page
- Add loading state on button click (not just after callback)
- Add onerror handler for script load failure
- Disable button until OIDC script is loaded
- Replace useCallback with ref pattern to prevent stale closures and
unnecessary Telegram.Login.init() re-calls
- Make isOIDC a proper boolean with Boolean() wrapper
- Clear previous error on successful login attempt
- Remove hardcoded fallback string from t() call
- Add oidc_enabled/oidc_client_id to TelegramWidgetConfig interface and fallback
- Add loginTelegramOIDC API method for id_token auth
- Add loginWithTelegramOIDC to auth store
- Rewrite TelegramLoginButton: OIDC popup when enabled, legacy widget otherwise
- Extend Window.Telegram type with Login SDK in vite-env.d.ts
- Upgrade telegram-widget.js from v22 to v23 (TelegramLoginButton + ConnectedAccounts)
- TelegramLoginButton fetches widget config from API instead of hardcoded values
- Add TelegramWidgetConfig type and API method with fallback to env defaults
- Remove botUsername prop — now sourced from backend API
- Add useEffect cleanup to prevent orphaned iframes on unmount
- Add TELEGRAM_WIDGET category to admin interface settings menu
- Add i18n translations for widget settings (ru, en, zh, fa)
Show sub-options (e.g. СБП, Карта) as selectable buttons when a
payment method has multiple enabled variants. Send suffixed
payment_method ID to backend for correct provider routing.
Split LandingPaymentMethod into public and admin types.
Add interactive sub-option toggles (Card/SBP/Crypto) to the landing editor
payment method configuration. Extract SortableFeatureItem and
SortableSelectedMethodCard into dedicated component files to reduce
AdminLandingEditor from ~1160 to ~860 lines.