import { useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { Alert, Button, Collapse, Descriptions, Divider, Form, Input, InputNumber, Select, Space, Switch } from 'antd'; import { RadarChartOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons'; import { FormField } from '@/components/form/rhf'; import { UTLS_FINGERPRINT } from '@/schemas/primitives'; import { validateRealityClientVer, validateRealityMaxClientVer, validateRealityTarget, } from '@/lib/xray/stream-wire-normalize'; import type { RealityScanResult } from '@/generated/types'; import RealityTargetScannerModal from './RealityTargetScannerModal'; interface RealityFormProps { saving: boolean; scanning: boolean; scanResult: RealityScanResult | null; scanRealityTarget: () => void; scanRealityCandidates: (targets?: string) => Promise; applyRealityScanResult: (result: RealityScanResult) => void; randomizeShortIds: () => void; randomizeSpiderX: () => void; genRealityKeypair: () => void; clearRealityKeypair: () => void; genMldsa65: () => void; clearMldsa65: () => void; } export default function RealityForm({ saving, scanning, scanResult, scanRealityTarget, scanRealityCandidates, applyRealityScanResult, randomizeShortIds, randomizeSpiderX, genRealityKeypair, clearRealityKeypair, genMldsa65, clearMldsa65, }: RealityFormProps) { const { t } = useTranslation(); const { getFieldState, trigger } = useFormContext(); const [scannerOpen, setScannerOpen] = useState(false); const maxClientVerPath = 'streamSettings.realitySettings.maxClientVer'; const revalidateMaxClientVer = () => { if (getFieldState(maxClientVerPath).error) { void trigger(maxClientVerPath); } }; return ( <> {scanResult && ( {scanResult.tlsVersion || '—'} {scanResult.alpn || '—'} {scanResult.curveID || '—'} {scanResult.certValid ? `${scanResult.certSubject} (${scanResult.certIssuer})` : t('pages.inbounds.form.scanCertInvalid')} {scanResult.latencyMs > 0 ? `${scanResult.latencyMs} ms` : '—'} } /> )} { const max = typeof value === 'string' ? value : ''; const min = formValues?.streamSettings?.realitySettings?.minClientVer; const errKey = validateRealityMaxClientVer(max, typeof min === 'string' ? min : ''); return errKey ? errKey : true; }, }} > {(['limitFallbackUpload', 'limitFallbackDownload'] as const).map((dir) => (
{t(`pages.inbounds.form.${dir}`)}
))} ), }, ]} /> setScannerOpen(false)} scanRealityCandidates={scanRealityCandidates} onPick={applyRealityScanResult} /> ); }