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

@@ -6058,7 +6058,15 @@
"shareModalActivateVia": "Активировать через бота:",
"shareModalActivateViaCabinet": "Или через сайт:",
"copyMessage": "Скопировать сообщение",
"shareToastCopied": "Сообщение скопировано"
"shareToastCopied": "Сообщение скопировано",
"qrHint": "Отсканируйте, чтобы активировать подарок",
"scanButton": "📷 Отсканировать QR",
"scanInProgress": "Сканирование…",
"scanCancel": "Остановить сканирование",
"scanDescription": "Наведите камеру на QR-код подарка",
"scanNotRecognized": "В QR-коде нет кода подарка",
"scanError": "Не удалось отсканировать",
"scanNoCamera": "Камера недоступна — введите код вручную"
},
"news": {
"title": "Новости и обновления",