diff --git a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx index 24016691..eafaa059 100644 --- a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx +++ b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx @@ -14,7 +14,6 @@ import { message, } from 'antd'; import { FinalMaskForm } from '@/lib/xray/forms/transport'; -import { HeaderMapEditor } from '@/components/form'; import { HysteriaMasqueradeForm } from '@/lib/xray/forms/protocols/shared'; import { JsonEditor } from '@/components/form'; import { Wireguard } from '@/utils'; @@ -50,7 +49,6 @@ import { ALPN_OPTIONS, FLOW_OPTIONS, HYSTERIA_NETWORK_OPTION, - MODE_OPTIONS, NETWORK_OPTIONS, PROTOCOL_OPTIONS, SERVER_PROTOCOLS, @@ -82,6 +80,7 @@ import { KcpForm, RawForm, WsForm, + XhttpForm, } from './transport'; import './OutboundFormModal.css'; @@ -524,345 +523,7 @@ export default function OutboundFormModal({ {network === 'httpupgrade' && } - {network === 'xhttp' && ( - <> - - - - - - - - - - - - - - {/* Padding obfs sub-section: gated by a Switch. - When on, four extra knobs (key/header/placement/ - method) tune how Xray injects random padding to - disguise the post body shape. */} - - - - - {() => { - const obfs = !!form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'xPaddingObfsMode', - ]); - if (!obfs) return null; - return ( - <> - - - - - - - - - - - ); - }} - - - - prev?.streamSettings?.xhttpSettings?.mode !== - curr?.streamSettings?.xhttpSettings?.mode - } - > - {() => { - const mode = form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'mode', - ]); - return ( - - - - - {() => { - const placement = form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'sessionPlacement', - ]); - if (!placement || placement === 'path') return null; - return ( - - - - ); - }} - - - - - ); - }} - - - {/* Mode-conditional sub-sections. */} - - {() => { - const mode = form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'mode', - ]); - if (mode !== 'packet-up') return null; - return ( - <> - - - - - - - - - - - - - - ); - }} - - - ); - }} - - - {() => { - const mode = form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'mode', - ]); - if (mode !== 'stream-up' && mode !== 'stream-one') return null; - return ( - - - - ); - }} - - - {/* XMUX is the connection-multiplexing layer - xHTTP uses to fan out parallel requests over - a small pool of upstream connections. UI-only - toggle (enableXmux) hides the 6 nested knobs - when off. */} - - - - - {() => { - if (!form.getFieldValue([ - 'streamSettings', 'xhttpSettings', 'enableXmux', - ])) return null; - return ( - <> - - - - - - - - - - - - - - - - - - - - ); - }} - - - )} + {network === 'xhttp' && } {network === 'hysteria' && ( <> diff --git a/frontend/src/pages/xray/outbounds/transport/index.ts b/frontend/src/pages/xray/outbounds/transport/index.ts index 9dd145b7..dfe6673f 100644 --- a/frontend/src/pages/xray/outbounds/transport/index.ts +++ b/frontend/src/pages/xray/outbounds/transport/index.ts @@ -3,3 +3,4 @@ export { default as KcpForm } from './kcp'; export { default as WsForm } from './ws'; export { default as GrpcForm } from './grpc'; export { default as HttpUpgradeForm } from './httpupgrade'; +export { default as XhttpForm } from './xhttp'; diff --git a/frontend/src/pages/xray/outbounds/transport/xhttp.tsx b/frontend/src/pages/xray/outbounds/transport/xhttp.tsx new file mode 100644 index 00000000..2b1e7332 --- /dev/null +++ b/frontend/src/pages/xray/outbounds/transport/xhttp.tsx @@ -0,0 +1,355 @@ +import { useTranslation } from 'react-i18next'; +import { Form, Input, InputNumber, Select, Switch, type FormInstance } from 'antd'; + +import { HeaderMapEditor } from '@/components/form'; +import type { OutboundFormValues } from '@/schemas/forms/outbound-form'; + +import { MODE_OPTIONS } from '../outbound-form-constants'; + +interface XhttpFormProps { + form: FormInstance; + onXmuxToggle: (checked: boolean) => void; +} + +export default function XhttpForm({ form, onXmuxToggle }: XhttpFormProps) { + const { t } = useTranslation(); + return ( + <> + + + + + + + + + + + + + + {/* Padding obfs sub-section: gated by a Switch. + When on, four extra knobs (key/header/placement/ + method) tune how Xray injects random padding to + disguise the post body shape. */} + + + + + {() => { + const obfs = !!form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'xPaddingObfsMode', + ]); + if (!obfs) return null; + return ( + <> + + + + + + + + + + + ); + }} + + + + prev?.streamSettings?.xhttpSettings?.mode !== + curr?.streamSettings?.xhttpSettings?.mode + } + > + {() => { + const mode = form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'mode', + ]); + return ( + + + + + {() => { + const placement = form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'sessionPlacement', + ]); + if (!placement || placement === 'path') return null; + return ( + + + + ); + }} + + + + + ); + }} + + + {/* Mode-conditional sub-sections. */} + + {() => { + const mode = form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'mode', + ]); + if (mode !== 'packet-up') return null; + return ( + <> + + + + + + + + + + + + + + ); + }} + + + ); + }} + + + {() => { + const mode = form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'mode', + ]); + if (mode !== 'stream-up' && mode !== 'stream-one') return null; + return ( + + + + ); + }} + + + {/* XMUX is the connection-multiplexing layer + xHTTP uses to fan out parallel requests over + a small pool of upstream connections. UI-only + toggle (enableXmux) hides the 6 nested knobs + when off. */} + + + + + {() => { + if (!form.getFieldValue([ + 'streamSettings', 'xhttpSettings', 'enableXmux', + ])) return null; + return ( + <> + + + + + + + + + + + + + + + + + + + + ); + }} + + + ); +}