Добавлен fallback через бота когда виджет Telegram не загружается:
- Таймаут 8 сек на загрузку скрипта (OIDC + legacy)
- Автоматический переход на deep link auth
- Polling каждые 2.5 сек до подтверждения в боте
- ConnectedAccounts: таймаут + сообщение при недоступности
- Переводы: ru, en, zh, fa
- add bot referral link section with Telegram icon (conditionally rendered)
- add cabinet referral link section with chain-link icon
- independent copy button state per link type
- add bot_referral_link to ReferralInfo type
- add i18n keys: botLink, cabinetLink in ru/en/fa/zh
- 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
- Use openInvoice() with capabilities.hasInvoice guard for Stars payments
- Fall back to redirect for web environments without invoice support
- Add haptic feedback on payment success/failure
Add promo group banner (green) and active discount banner (orange) to
gift subscription page. PeriodCard now shows original price strikethrough
and discount percentage badge from server-calculated values.
Use createPortal to render toast at document.body level,
escaping framer-motion's transform on the tab content wrapper.
Remove unused useRef import and shareToastTapCopy i18n key.
GiftResult.tsx referenced gift.shareModalCopied and shareModalCopyAll
which were removed with the modal. Use common.copied and add new
gift.copyMessage key instead.
Remove the full-screen ShareModal dialog that appeared when sharing a
gift code. Replace with a bottom toast that automatically copies the
share message to clipboard on button press and slides up from the
bottom. The toast auto-dismisses after 5 seconds and can be tapped
to copy again.
GIFTCODE_ prefix (9 chars) + full 64-char token = 73 chars,
exceeding Telegram's 64-char start parameter limit. Now all
share links use the same short code shown in the UI (first 12
chars). Backend already supports prefix-based lookup.
- Fix Russian device count declension (_one/_few/_many)
- Show traffic GB and tariff description in buy tab
- Replace copy/share buttons with share modal (bot + cabinet links)
- GiftResult: code-only success state with formatted share message
- Support ?tab=activate&code=TOKEN for auto-activation via cabinet link
- Add is_code_only + purchase_token to API types
- Remove recipient input from buy flow (code-only gifts)
- 3-tab UI: Buy, Activate, My Gifts with animations
- After purchase, switch to My Gifts tab to show gift code
- Gift code display with copy/share buttons
- Activate tab: enter gift code to activate subscription
- My Gifts tab: sent/received gifts with status badges
- Fix: use navigator.language instead of hardcoded ru-RU for dates
- Fix: spread array before sort to prevent React Query cache mutation
- Fix: ARIA tab linkage with proper id/aria-labelledby
- Fix: guard VITE_BOT_USERNAME against undefined in share URLs
- Fix: wrap clipboard/share fallbacks in try/catch
- Add error state to MyGiftsTabContent
When all periods are removed from a tariff, users saw an empty
purchase form with no way to renew. Now shows a message explaining
the situation and a button to choose a different tariff.
- 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
- Added is_default toggle to promo group create/edit form
- Send 0 instead of null when clearing auto-assign threshold
- Added isDefault i18n keys for ru, en, zh, fa
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 warning field to GiftPurchaseStatus type
- Read warning from status response with URL param fallback
- Show PollErrorState for all poll errors (softer UX for gateway payments)
- 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
TelegramLinkWidget used legacy widget only, ignoring OIDC config.
Now queries widgetConfig from backend, supports OIDC popup flow with
id_token, and falls back to bot_username from server config.
- Move PAID_STATUSES/FAILED_STATUSES from Balance.tsx and TopUpResult.tsx
to src/utils/paymentStatus.ts
- Eliminates code duplication between the two pages