Refactor QR code implementation in ConfigCard, SubscriptionCard, TelegramLinkCard, and TelegramLoginButton components
- 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:
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { useTranslation } from 'react-i18next'
|
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 { Copy, QrCode, RefreshCw, Trash2 } from 'lucide-react'
|
||||||
import { toast } from '@/shared/ui/toast-store'
|
import { toast } from '@/shared/ui/toast-store'
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card'
|
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/ui/card'
|
||||||
@@ -119,7 +119,7 @@ export function ConfigCard({ config }: { config: VpnConfigDto }) {
|
|||||||
)}
|
)}
|
||||||
{linkQuery.data && (
|
{linkQuery.data && (
|
||||||
<div className="flex flex-col items-center gap-4">
|
<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">
|
<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">
|
<code className="min-w-0 flex-1 truncate rounded-md bg-muted px-2 py-1.5 text-xs">
|
||||||
{linkQuery.data.connectionString}
|
{linkQuery.data.connectionString}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { QRCodeSVG } from 'qrcode.react'
|
import { QrCode } from '@/shared/ui/qr-code'
|
||||||
import { Copy } from 'lucide-react'
|
import { Copy } from 'lucide-react'
|
||||||
import { toast } from '@/shared/ui/toast-store'
|
import { toast } from '@/shared/ui/toast-store'
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
|
||||||
@@ -30,7 +30,7 @@ export function SubscriptionCard() {
|
|||||||
<CardDescription>{t('configs.aggregatedSubscriptionHint')}</CardDescription>
|
<CardDescription>{t('configs.aggregatedSubscriptionHint')}</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex items-center gap-4">
|
<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">
|
<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>
|
<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()}>
|
<Button size="sm" variant="outline" onClick={() => void copy()}>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { useTranslation } from 'react-i18next'
|
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 { toast } from '@/shared/ui/toast-store'
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card'
|
||||||
import { Button } from '@/shared/ui/button'
|
import { Button } from '@/shared/ui/button'
|
||||||
@@ -87,7 +87,7 @@ export function TelegramLinkCard() {
|
|||||||
<div className="flex flex-col items-center gap-4">
|
<div className="flex flex-col items-center gap-4">
|
||||||
{deepLink ? (
|
{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">
|
<a href={deepLink} target="_blank" rel="noreferrer" className="text-sm text-primary hover:underline">
|
||||||
{deepLink}
|
{deepLink}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
|
|||||||
import { useMutation, useQuery } from '@tanstack/react-query'
|
import { useMutation, useQuery } from '@tanstack/react-query'
|
||||||
import { useNavigate } from '@tanstack/react-router'
|
import { useNavigate } from '@tanstack/react-router'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { QRCodeSVG } from 'qrcode.react'
|
import { QrCode } from '@/shared/ui/qr-code'
|
||||||
import { Send } from 'lucide-react'
|
import { Send } from 'lucide-react'
|
||||||
import { toast } from '@/shared/ui/toast-store'
|
import { toast } from '@/shared/ui/toast-store'
|
||||||
import { Button } from '@/shared/ui/button'
|
import { Button } from '@/shared/ui/button'
|
||||||
@@ -68,7 +68,7 @@ export function TelegramLoginButton() {
|
|||||||
<div className="flex flex-col items-center gap-4">
|
<div className="flex flex-col items-center gap-4">
|
||||||
{deepLink && (
|
{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">
|
<a href={deepLink} target="_blank" rel="noreferrer" className="text-sm text-primary hover:underline">
|
||||||
{deepLink}
|
{deepLink}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user