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

@@ -5504,7 +5504,15 @@
"shareModalActivateVia": "Activate via bot:",
"shareModalActivateViaCabinet": "Or via website:",
"copyMessage": "Copy message",
"shareToastCopied": "Message copied"
"shareToastCopied": "Message copied",
"qrHint": "Scan to activate the gift",
"scanButton": "📷 Scan QR",
"scanInProgress": "Scanning…",
"scanCancel": "Stop scanning",
"scanDescription": "Point the camera at the gift QR code",
"scanNotRecognized": "No gift code in this QR",
"scanError": "Could not scan",
"scanNoCamera": "Camera unavailable — enter the code manually"
},
"news": {
"title": "News & Updates",