mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 05:04:22 +00:00
fix(frontend): derive QUIC/UDP-hop switch state from data presence (B22)
The QUIC Params and UDP Hop toggles previously persisted as separate boolean flags (enableQuicParams / hasUdpHop) which weren't part of the xray wire format and weren't restored when a config was pasted into the modal. Use data presence as the single source of truth: the switch is on iff the corresponding sub-object exists. Switching off clears it back to undefined.
This commit is contained in:
parent
66deec95ae
commit
6e90b24af1
1 changed files with 19 additions and 17 deletions
|
|
@ -80,18 +80,11 @@ function defaultNoiseItem(): Record<string, unknown> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultQuicParams(): Record<string, unknown> {
|
function defaultQuicParams(): Record<string, unknown> {
|
||||||
// Seeded with the xray-core / hysteria recommended defaults so the QUIC
|
|
||||||
// Params sub-form doesn't show blank InputNumber fields when first
|
|
||||||
// enabled. The schema declares these as .optional() (no Zod default)
|
|
||||||
// because the wire shape omits them when xray's built-in default
|
|
||||||
// applies — but the panel needs values to render the controls.
|
|
||||||
return {
|
return {
|
||||||
congestion: 'bbr',
|
congestion: 'bbr',
|
||||||
debug: false,
|
debug: false,
|
||||||
brutalUp: 0,
|
brutalUp: 0,
|
||||||
brutalDown: 0,
|
brutalDown: 0,
|
||||||
hasUdpHop: false,
|
|
||||||
udpHop: { ports: '20000-50000', interval: '5-10' },
|
|
||||||
maxIdleTimeout: 30,
|
maxIdleTimeout: 30,
|
||||||
keepAlivePeriod: 10,
|
keepAlivePeriod: 10,
|
||||||
disablePathMTUDiscovery: false,
|
disablePathMTUDiscovery: false,
|
||||||
|
|
@ -103,13 +96,18 @@ function defaultQuicParams(): Record<string, unknown> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defaultUdpHop(): Record<string, unknown> {
|
||||||
|
return { ports: '20000-50000', interval: '5-10' };
|
||||||
|
}
|
||||||
|
|
||||||
export default function FinalMaskForm({ name, network, protocol, form }: FinalMaskFormProps) {
|
export default function FinalMaskForm({ name, network, protocol, form }: FinalMaskFormProps) {
|
||||||
const base = asPath(name);
|
const base = asPath(name);
|
||||||
const isHysteria = protocol === OutboundProtocols.Hysteria || protocol === 'hysteria';
|
const isHysteria = protocol === OutboundProtocols.Hysteria || protocol === 'hysteria';
|
||||||
const showTcp = TCP_NETWORKS.includes(network);
|
const showTcp = TCP_NETWORKS.includes(network);
|
||||||
const showUdp = isHysteria || network === 'kcp';
|
const showUdp = isHysteria || network === 'kcp';
|
||||||
const showQuic = isHysteria || network === 'xhttp';
|
const showQuic = isHysteria || network === 'xhttp';
|
||||||
const enableQuic = Form.useWatch([...base, 'enableQuicParams'], form);
|
const quicParams = Form.useWatch([...base, 'quicParams'], { form, preserve: true });
|
||||||
|
const hasQuicParams = quicParams != null;
|
||||||
|
|
||||||
if (!showTcp && !showUdp && !showQuic) return null;
|
if (!showTcp && !showUdp && !showQuic) return null;
|
||||||
|
|
||||||
|
|
@ -119,17 +117,15 @@ export default function FinalMaskForm({ name, network, protocol, form }: FinalMa
|
||||||
{showUdp && <UdpMasksList base={base} form={form} isHysteria={isHysteria} network={network} />}
|
{showUdp && <UdpMasksList base={base} form={form} isHysteria={isHysteria} network={network} />}
|
||||||
{showQuic && (
|
{showQuic && (
|
||||||
<>
|
<>
|
||||||
<Form.Item label="QUIC Params" name={[...base, 'enableQuicParams']} valuePropName="checked">
|
<Form.Item label="QUIC Params">
|
||||||
<Switch
|
<Switch
|
||||||
|
checked={hasQuicParams}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
if (v) {
|
form.setFieldValue([...base, 'quicParams'], v ? defaultQuicParams() : undefined);
|
||||||
const current = form.getFieldValue([...base, 'quicParams']);
|
|
||||||
if (!current) form.setFieldValue([...base, 'quicParams'], defaultQuicParams());
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{enableQuic && <QuicParamsForm base={[...base, 'quicParams']} form={form} />}
|
{hasQuicParams && <QuicParamsForm base={[...base, 'quicParams']} form={form} />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
@ -669,7 +665,8 @@ function ItemEditor({
|
||||||
|
|
||||||
function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormInstance }) {
|
function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormInstance }) {
|
||||||
const congestion = Form.useWatch([...base, 'congestion'], form) as string | undefined;
|
const congestion = Form.useWatch([...base, 'congestion'], form) as string | undefined;
|
||||||
const hasUdpHop = Form.useWatch([...base, 'hasUdpHop'], form) as boolean | undefined;
|
const udpHop = Form.useWatch([...base, 'udpHop'], { form, preserve: true }) as Record<string, unknown> | undefined;
|
||||||
|
const hasUdpHop = udpHop != null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -698,8 +695,13 @@ function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormI
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Form.Item label="UDP Hop" name={[...base, 'hasUdpHop']} valuePropName="checked">
|
<Form.Item label="UDP Hop">
|
||||||
<Switch />
|
<Switch
|
||||||
|
checked={hasUdpHop}
|
||||||
|
onChange={(v) => {
|
||||||
|
form.setFieldValue([...base, 'udpHop'], v ? defaultUdpHop() : undefined);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{hasUdpHop && (
|
{hasUdpHop && (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue