Refactor QR code implementation in ConfigCard, SubscriptionCard, TelegramLinkCard, and TelegramLoginButton components
CI / Backend (build + test) (push) Failing after 2m36s
CI / Frontend (lint + typecheck + build) (push) Successful in 56s

- Replaced `QRCodeSVG` with a new `QrCode` component from the shared UI library across multiple files, enhancing consistency in QR code rendering.
- Adjusted sizes of QR codes in `ConfigCard` and `SubscriptionCard` for improved visual presentation.
This commit is contained in:
Leonid Pershin
2026-07-28 19:08:27 +03:00
parent 9925968e22
commit a8358b930d
5 changed files with 41 additions and 8 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { QRCodeSVG } from 'qrcode.react'
import { QrCode as QrCodeImage } from '@/shared/ui/qr-code'
import { Copy, QrCode, RefreshCw, Trash2 } from 'lucide-react'
import { toast } from '@/shared/ui/toast-store'
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card'
@@ -119,7 +119,7 @@ export function ConfigCard({ config }: { config: VpnConfigDto }) {
)}
{linkQuery.data && (
<div className="flex flex-col items-center gap-4">
<QRCodeSVG value={linkQuery.data.connectionString} size={200} />
<QrCodeImage value={linkQuery.data.connectionString} size={240} />
<div className="flex w-full items-center gap-2">
<code className="min-w-0 flex-1 truncate rounded-md bg-muted px-2 py-1.5 text-xs">
{linkQuery.data.connectionString}
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { QRCodeSVG } from 'qrcode.react'
import { QrCode } from '@/shared/ui/qr-code'
import { Copy } from 'lucide-react'
import { toast } from '@/shared/ui/toast-store'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
@@ -30,7 +30,7 @@ export function SubscriptionCard() {
<CardDescription>{t('configs.aggregatedSubscriptionHint')}</CardDescription>
</CardHeader>
<CardContent className="flex items-center gap-4">
<QRCodeSVG value={data.subscriptionUrl} size={96} />
<QrCode value={data.subscriptionUrl} size={112} />
<div className="flex min-w-0 flex-1 flex-col gap-2">
<code className="truncate rounded-md bg-muted px-2 py-1.5 text-xs">{data.subscriptionUrl}</code>
<Button size="sm" variant="outline" onClick={() => void copy()}>
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { QRCodeSVG } from 'qrcode.react'
import { QrCode } from '@/shared/ui/qr-code'
import { toast } from '@/shared/ui/toast-store'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
import { Button } from '@/shared/ui/button'
@@ -87,7 +87,7 @@ export function TelegramLinkCard() {
<div className="flex flex-col items-center gap-4">
{deepLink ? (
<>
<QRCodeSVG value={deepLink} size={200} />
<QrCode value={deepLink} size={200} />
<a href={deepLink} target="_blank" rel="noreferrer" className="text-sm text-primary hover:underline">
{deepLink}
</a>
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
import { useMutation, useQuery } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { QRCodeSVG } from 'qrcode.react'
import { QrCode } from '@/shared/ui/qr-code'
import { Send } from 'lucide-react'
import { toast } from '@/shared/ui/toast-store'
import { Button } from '@/shared/ui/button'
@@ -68,7 +68,7 @@ export function TelegramLoginButton() {
<div className="flex flex-col items-center gap-4">
{deepLink && (
<>
<QRCodeSVG value={deepLink} size={200} />
<QrCode value={deepLink} size={200} />
<a href={deepLink} target="_blank" rel="noreferrer" className="text-sm text-primary hover:underline">
{deepLink}
</a>
+33
View File
@@ -0,0 +1,33 @@
import { QRCodeSVG } from 'qrcode.react'
import { cn } from '@/shared/lib/cn'
export type QrCodeProps = {
value: string
size?: number
className?: string
}
/**
* QR всегда рисуем тёмным по белому, с quiet zone и уровнем коррекции M: дефолты qrcode.react
* (marginSize=0, level="L") дают код впритык к тёмному фону диалога — камеры и встроенные
* сканеры VPN-клиентов такой код не находят. Белая подложка + color-scheme:light дополнительно
* гасит force-dark мобильных браузеров, который инвертирует SVG и делает QR нечитаемым.
*/
export function QrCode({ value, size = 224, className }: QrCodeProps) {
return (
<div
className={cn('shrink-0 rounded-md bg-white p-3 [color-scheme:light]', className)}
style={{ width: size + 24, maxWidth: '100%' }}
>
<QRCodeSVG
value={value}
size={size}
level="M"
marginSize={2}
bgColor="#FFFFFF"
fgColor="#000000"
className="h-auto w-full"
/>
</div>
)
}