diff --git a/frontend/src/pages/xray/OutboundFormModal.new.tsx b/frontend/src/pages/xray/OutboundFormModal.new.tsx index 02876046..b8993dc6 100644 --- a/frontend/src/pages/xray/OutboundFormModal.new.tsx +++ b/frontend/src/pages/xray/OutboundFormModal.new.tsx @@ -32,6 +32,7 @@ import { } from '@/schemas/forms/outbound-form'; import { ALPN_OPTION, + Address_Port_Strategy, DNSRuleActions, MODE_OPTION, OutboundDomainStrategies, @@ -72,6 +73,20 @@ const SS_METHOD_OPTIONS = SSMethodSchema.options.map((v) => ({ value: v, label: const MODE_OPTIONS = Object.values(MODE_OPTION).map((v) => ({ value: v, label: v })); const UTLS_OPTIONS = Object.values(UTLS_FINGERPRINT).map((v) => ({ value: v, label: v })); const ALPN_OPTIONS = Object.values(ALPN_OPTION).map((v) => ({ value: v, label: v })); +const ADDRESS_PORT_STRATEGY_OPTIONS = Object.values(Address_Port_Strategy).map((v) => ({ + value: v, + label: v, +})); + +// canEnableMux mirrors the adapter's helper but lives here so the modal +// can show/hide the Mux section without going through the adapter. +const MUX_PROTOCOLS = new Set(['vmess', 'vless', 'trojan', 'shadowsocks', 'http', 'socks']); +function isMuxAllowed(protocol: string, flow: string, network: string): boolean { + if (!MUX_PROTOCOLS.has(protocol)) return false; + if (protocol === 'vless' && flow) return false; + if (network === 'xhttp') return false; + return true; +} const NETWORK_OPTIONS: { value: string; label: string }[] = [ { value: 'tcp', label: 'TCP (RAW)' }, @@ -1289,6 +1304,159 @@ export default function OutboundFormModalNew({ )} + + {streamAllowed && network && ( + + {() => { + const hasSockopt = !!form.getFieldValue([ + 'streamSettings', + 'sockopt', + ]); + return ( + <> + + { + form.setFieldValue( + ['streamSettings', 'sockopt'], + checked + ? { + acceptProxyProtocol: false, + tcpFastOpen: false, + mark: 0, + tproxy: 'off', + tcpMptcp: false, + penetrate: false, + domainStrategy: 'UseIP', + tcpMaxSeg: 1440, + dialerProxy: '', + tcpKeepAliveInterval: 0, + tcpKeepAliveIdle: 300, + tcpUserTimeout: 10000, + tcpcongestion: 'bbr', + V6Only: false, + tcpWindowClamp: 600, + interfaceName: '', + trustedXForwardedFor: [], + } + : undefined, + ); + }} + /> + + {hasSockopt && ( + <> + + + + + + + + )} + + ); + }} + + )} + + {(() => { + const flow = (form.getFieldValue(['settings', 'flow']) ?? '') as string; + if (!isMuxAllowed(protocol, flow, network)) return null; + return ( + + {() => { + const muxEnabled = !!form.getFieldValue(['mux', 'enabled']); + return ( + <> + + + + {muxEnabled && ( + <> + + + + + + + +