feat(gift): QR подарка и сканирование в кабинете

Получателю раньше оставалось только скопировать ссылку или код руками.

- QR на экране готового подарка: кодируется bot-ссылка (активация в боте —
  основной путь), при отсутствии username бота — ссылка кабинета. Использован
  уже имеющийся qrcode.react, на белой подложке ради контраста в тёмной теме.
- Кнопка «Отсканировать QR» в форме активации. В Telegram используется
  НАТИВНЫЙ сканер (в WebView камера через getUserMedia работает ненадёжно —
  ровно то, из-за чего скан «в тг» и был проблемой), в вебе — html5-qrcode с
  CDN, с фолбэком на фронтальную камеру и понятной ошибкой, если камеры нет.
- src/utils/qrScanner.ts: логика сканера вынесена из TvQuickConnect, чтобы её
  мог переиспользовать любой экран. parseGiftCode понимает все три способа
  распространения подарка (deep-link бота, ссылка кабинета, голый код с
  префиксом GIFT- и без) и ОТКЛОНЯЕТ посторонние QR — иначе сканер подставил
  бы в поле мусор с любой ссылки или Wi-Fi-кода.
- Веб-сканер гасится при уходе с вкладки и размонтировании, иначе индикатор
  камеры остаётся гореть.

Локали ru/en/zh/fa, +4 теста на парсер.
This commit is contained in:
Fringg
2026-07-29 22:11:04 +03:00
parent 390da33914
commit 0e4dc43335
8 changed files with 281 additions and 5 deletions

View File

@@ -5012,7 +5012,15 @@
"tabActivate": "فعال‌سازی",
"tabBuy": "خرید",
"tabMyGifts": "هدایای من",
"unlimitedTraffic": "ترافیک نامحدود"
"unlimitedTraffic": "ترافیک نامحدود",
"qrHint": "برای فعال‌سازی هدیه اسکن کنید",
"scanButton": "📷 اسکن QR",
"scanInProgress": "در حال اسکن…",
"scanCancel": "توقف اسکن",
"scanDescription": "دوربین را روی کد QR هدیه بگیرید",
"scanNotRecognized": "در این QR کد هدیه‌ای نیست",
"scanError": "اسکن ناموفق بود",
"scanNoCamera": "دوربین در دسترس نیست — کد را دستی وارد کنید"
},
"news": {
"title": "اخبار و به‌روزرسانی‌ها",