From 2aec8031812b5e5bfc57b2a1438de2396d21f252 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 30 May 2026 20:37:57 +0200 Subject: [PATCH] refactor(frontend): extract outbound sockopt/mux/hysteria transport blocks Move the last three oversized inline stream blocks out of OutboundFormModal into presentational components under xray/outbounds/transport/: SockoptForm (~260 lines, the worst offender), MuxForm, and HysteriaForm. Each takes the form instance; MuxForm also takes protocol/network and keeps its isMuxAllowed gate. OutboundFormModal drops from 962 to 621 lines and no inline section now exceeds the 250-line guideline. Existing outbound-form-modal snapshots already cover sockopt/mux and stay byte-identical, confirming no behavior change. --- .../xray/outbounds/OutboundFormModal.tsx | 357 +----------------- .../xray/outbounds/transport/hysteria.tsx | 32 ++ .../pages/xray/outbounds/transport/index.ts | 3 + .../pages/xray/outbounds/transport/mux.tsx | 63 ++++ .../xray/outbounds/transport/sockopt.tsx | 276 ++++++++++++++ 5 files changed, 382 insertions(+), 349 deletions(-) create mode 100644 frontend/src/pages/xray/outbounds/transport/hysteria.tsx create mode 100644 frontend/src/pages/xray/outbounds/transport/mux.tsx create mode 100644 frontend/src/pages/xray/outbounds/transport/sockopt.tsx diff --git a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx index 0e340ddb..51f3bb73 100644 --- a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx +++ b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx @@ -1,7 +1,6 @@ import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { - Button, Form, Input, InputNumber, @@ -13,7 +12,7 @@ import { Tabs, message, } from 'antd'; -import { FinalMaskForm, HysteriaMasqueradeForm } from '@/lib/xray/forms/transport'; +import { FinalMaskForm } from '@/lib/xray/forms/transport'; import { JsonEditor } from '@/components/form'; import { Wireguard } from '@/utils'; import { @@ -26,15 +25,7 @@ import { OutboundFormBaseSchema, type OutboundFormValues, } from '@/schemas/forms/outbound-form'; -import { - DOMAIN_STRATEGY_OPTION, - SNIFFING_OPTION, - TCP_CONGESTION_OPTION, -} from '@/schemas/primitives'; -import { - HappyEyeballsSchema, - SockoptStreamSettingsSchema, -} from '@/schemas/protocols/stream/sockopt'; +import { SNIFFING_OPTION } from '@/schemas/primitives'; import { canEnableReality, canEnableStream, @@ -44,7 +35,6 @@ import { import { antdRule } from '@/utils/zodForm'; import { - ADDRESS_PORT_STRATEGY_OPTIONS, FLOW_OPTIONS, HYSTERIA_NETWORK_OPTION, NETWORK_OPTIONS, @@ -54,7 +44,6 @@ import { import { buildAddModeValues, hysteriaStreamSlice, - isMuxAllowed, newStreamSlice, } from './outbound-form-helpers'; import { @@ -74,8 +63,11 @@ import { import { GrpcForm, HttpUpgradeForm, + HysteriaForm, KcpForm, + MuxForm, RawForm, + SockoptForm, WsForm, XhttpForm, } from './transport'; @@ -523,29 +515,7 @@ export default function OutboundFormModal({ {network === 'xhttp' && } - {network === 'hysteria' && ( - <> - - - - - - - - - - - - )} + {network === 'hysteria' && } )} @@ -605,270 +575,7 @@ export default function OutboundFormModal({ {security === 'reality' && realityAllowed && } - {((streamAllowed && network) || !streamAllowed) && ( - - {() => { - const hasSockopt = !!form.getFieldValue([ - 'streamSettings', - 'sockopt', - ]); - return ( - <> - - { - form.setFieldValue( - ['streamSettings', 'sockopt'], - checked ? SockoptStreamSettingsSchema.parse({}) : undefined, - ); - }} - /> - - {hasSockopt && ( - <> - - - - - - - - - - - - - - - - - - - - - - - - - - ({ - value: v, - label: v, - }))} - /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ))} - - )} - - - )} - - ); - }} - - )} + {((streamAllowed && network) || !streamAllowed) && } - {(() => { - const flow = (form.getFieldValue(['settings', 'flow']) ?? '') as string; - if (!isMuxAllowed(protocol, flow, network)) return null; - return ( - - {() => { - const muxEnabled = !!form.getFieldValue(['mux', 'enabled']); - return ( - <> - - - - {muxEnabled && ( - <> - - - - - - - - + + + + + + + ); +} diff --git a/frontend/src/pages/xray/outbounds/transport/index.ts b/frontend/src/pages/xray/outbounds/transport/index.ts index dfe6673f..38ce4d5e 100644 --- a/frontend/src/pages/xray/outbounds/transport/index.ts +++ b/frontend/src/pages/xray/outbounds/transport/index.ts @@ -4,3 +4,6 @@ export { default as WsForm } from './ws'; export { default as GrpcForm } from './grpc'; export { default as HttpUpgradeForm } from './httpupgrade'; export { default as XhttpForm } from './xhttp'; +export { default as HysteriaForm } from './hysteria'; +export { default as SockoptForm } from './sockopt'; +export { default as MuxForm } from './mux'; diff --git a/frontend/src/pages/xray/outbounds/transport/mux.tsx b/frontend/src/pages/xray/outbounds/transport/mux.tsx new file mode 100644 index 00000000..e9a51283 --- /dev/null +++ b/frontend/src/pages/xray/outbounds/transport/mux.tsx @@ -0,0 +1,63 @@ +import { useTranslation } from 'react-i18next'; +import { Form, InputNumber, Select, Switch, type FormInstance } from 'antd'; + +import type { OutboundFormValues } from '@/schemas/forms/outbound-form'; + +import { isMuxAllowed } from '../outbound-form-helpers'; + +interface MuxFormProps { + form: FormInstance; + protocol: string; + network: string; +} + +export default function MuxForm({ form, protocol, network }: MuxFormProps) { + const { t } = useTranslation(); + const flow = (form.getFieldValue(['settings', 'flow']) ?? '') as string; + if (!isMuxAllowed(protocol, flow, network)) return null; + return ( + + {() => { + const muxEnabled = !!form.getFieldValue(['mux', 'enabled']); + return ( + <> + + + + {muxEnabled && ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ({ + value: v, + label: v, + }))} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + )} + + + )} + + ); + }} + + ); +}