Hide TCP VLESS tab by default
This commit is contained in:
parent
97e7a4a3bb
commit
081bedd637
@ -33,15 +33,40 @@ export type VlessQrCopy = {
|
||||
interface VlessQrCardProps {
|
||||
uuid: string | null | undefined
|
||||
copy: VlessQrCopy
|
||||
defaultTransport?: VlessTransport
|
||||
visibleTransports?: VlessTransport[]
|
||||
}
|
||||
|
||||
const DEFAULT_TRANSPORT: VlessTransport = 'xhttp'
|
||||
const DEFAULT_VISIBLE_TRANSPORTS: VlessTransport[] = ['xhttp']
|
||||
|
||||
function normalizeVisibleTransports(transports?: VlessTransport[]): VlessTransport[] {
|
||||
const visible = (transports ?? DEFAULT_VISIBLE_TRANSPORTS).filter(
|
||||
(transport, index, values) => values.indexOf(transport) === index,
|
||||
)
|
||||
|
||||
return visible.length > 0 ? visible : DEFAULT_VISIBLE_TRANSPORTS
|
||||
}
|
||||
|
||||
function resolveInitialTransport(defaultTransport: VlessTransport | undefined, visibleTransports: VlessTransport[]): VlessTransport {
|
||||
if (defaultTransport && visibleTransports.includes(defaultTransport)) {
|
||||
return defaultTransport
|
||||
}
|
||||
|
||||
return visibleTransports[0] ?? DEFAULT_TRANSPORT
|
||||
}
|
||||
|
||||
|
||||
export default function VlessQrCard({
|
||||
uuid,
|
||||
copy,
|
||||
defaultTransport,
|
||||
visibleTransports,
|
||||
}: VlessQrCardProps) {
|
||||
const { data: allNodes, error: nodesError } = useSWR<VlessNode[]>('user-center-agent-nodes', fetchAgentNodes)
|
||||
|
||||
const transportOptions = useMemo(() => normalizeVisibleTransports(visibleTransports), [visibleTransports])
|
||||
|
||||
const nodes = useMemo(() => {
|
||||
return (allNodes ?? []).filter((node) => {
|
||||
const name = (node.name || '').toLowerCase()
|
||||
@ -53,7 +78,9 @@ export default function VlessQrCard({
|
||||
})
|
||||
}, [allNodes])
|
||||
const [selectedNode, setSelectedNode] = useState<VlessNode | null>(null)
|
||||
const [preferredTransport, setPreferredTransport] = useState<VlessTransport>('tcp')
|
||||
const [preferredTransport, setPreferredTransport] = useState<VlessTransport>(() =>
|
||||
resolveInitialTransport(defaultTransport, transportOptions),
|
||||
)
|
||||
const [isSelectorOpen, setIsSelectorOpen] = useState(false)
|
||||
|
||||
const [qrDataUrl, setQrDataUrl] = useState<string | null>(null)
|
||||
@ -61,6 +88,16 @@ export default function VlessQrCard({
|
||||
const [generationError, setGenerationError] = useState<string | null>(null)
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setPreferredTransport((currentTransport) => {
|
||||
if (transportOptions.includes(currentTransport)) {
|
||||
return currentTransport
|
||||
}
|
||||
|
||||
return resolveInitialTransport(defaultTransport, transportOptions)
|
||||
})
|
||||
}, [defaultTransport, transportOptions])
|
||||
|
||||
const rawNode = useMemo(() => {
|
||||
if (selectedNode) return selectedNode
|
||||
|
||||
@ -238,7 +275,7 @@ export default function VlessQrCard({
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
{(['tcp', 'xhttp'] as const).map((transport) => (
|
||||
{transportOptions.map((transport) => (
|
||||
<button
|
||||
key={transport}
|
||||
type="button"
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
import React from 'react'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import VlessQrCard, { type VlessQrCopy } from '../VlessQrCard'
|
||||
|
||||
vi.mock('next/image', () => ({
|
||||
default: () => null,
|
||||
}))
|
||||
|
||||
vi.mock('qrcode', () => ({
|
||||
toDataURL: vi.fn(() => Promise.resolve('data:image/png;base64,test')),
|
||||
}))
|
||||
|
||||
vi.mock('swr', () => ({
|
||||
default: vi.fn(() => ({
|
||||
data: [
|
||||
{
|
||||
name: 'JP-XHTTP.SVC.PLUS',
|
||||
address: 'jp-xhttp.svc.plus',
|
||||
port: 443,
|
||||
xhttp_port: 443,
|
||||
tcp_port: 1443,
|
||||
uri_scheme_xhttp: 'vless://${UUID}@${DOMAIN}:443?type=xhttp&path=${PATH}#${TAG}',
|
||||
uri_scheme_tcp: 'vless://${UUID}@${DOMAIN}:1443?type=tcp&flow=${FLOW}#${TAG}',
|
||||
},
|
||||
],
|
||||
error: undefined,
|
||||
})),
|
||||
}))
|
||||
|
||||
const copy: VlessQrCopy = {
|
||||
label: 'VLESS QR',
|
||||
description: 'Scan to import VLESS config.',
|
||||
linkLabel: 'VLESS link',
|
||||
linkHelper: 'Copy link helper',
|
||||
copyLink: 'Copy link',
|
||||
copied: 'Copied',
|
||||
downloadQr: 'Download QR',
|
||||
generating: 'Generating',
|
||||
error: 'Failed to generate',
|
||||
missingUuid: 'Missing UUID',
|
||||
qrAlt: 'VLESS QR code',
|
||||
}
|
||||
|
||||
describe('VlessQrCard', () => {
|
||||
it('only renders the XHTTP transport tab by default', () => {
|
||||
render(<VlessQrCard uuid="11111111-1111-4111-8111-111111111111" copy={copy} />)
|
||||
|
||||
expect(screen.getByRole('button', { name: /xhttp/i })).toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: /tcp/i })).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user