feat(frontend): FinalMaskForm rewrite to Pattern A + wire into both modals

Rewrite FinalMaskForm.tsx from a class-coupled component (mutated
stream.finalmask.tcp[] via .addTcpMask/.delTcpMask methods, notified
parent via onChange callback) into a Pattern A sub-form: takes a
NamePath base, a FormInstance, and the surrounding network/protocol,
then composes Form.List + Form.Item at absolute paths under that base.

All array structures use nested Form.List — tcp/udp mask arrays, the
clients/servers groups in header-custom (Form.List of Form.List of
ItemEditor), and the noise list. Type Selects use onChange to reset
the settings sub-object via form.setFieldValue, mirroring the legacy
changeMaskType behavior. The kcp.mtu side effect on xdns type change
is preserved.

Wired into both InboundFormModal and OutboundFormModal stream tabs,
placed after the sockopt section. The component is the first Pattern A
consumer of nested Form.List inside another Form.List, so it stands
as the reference for future nested-array sub-forms.
This commit is contained in:
MHSanaei
2026-05-26 14:38:53 +02:00
parent 34590dc327
commit e978428ca3
3 changed files with 513 additions and 608 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,7 @@ import { SockoptStreamSettingsSchema } from '@/schemas/protocols/stream/sockopt'
import { TlsStreamSettingsSchema } from '@/schemas/protocols/security/tls';
import { RealityStreamSettingsSchema } from '@/schemas/protocols/security/reality';
import DateTimePicker from '@/components/DateTimePicker';
import FinalMaskForm from '@/components/FinalMaskForm';
import HeaderMapEditor from '@/components/HeaderMapEditor';
import InputAddon from '@/components/InputAddon';
import JsonEditor from '@/components/JsonEditor';
@@ -2022,6 +2023,13 @@ export default function InboundFormModal({
</Form.Item>
</>
)}
<FinalMaskForm
name={['streamSettings', 'finalmask']}
network={network as string}
protocol={protocol}
form={form}
/>
</>
);

View File

@@ -15,6 +15,7 @@ import {
} from 'antd';
import { DeleteOutlined, MinusOutlined, PlusOutlined, SyncOutlined } from '@ant-design/icons';
import FinalMaskForm from '@/components/FinalMaskForm';
import HeaderMapEditor from '@/components/HeaderMapEditor';
import InputAddon from '@/components/InputAddon';
import JsonEditor from '@/components/JsonEditor';
@@ -2140,6 +2141,13 @@ export default function OutboundFormModal({
</Form.Item>
)}
<FinalMaskForm
name={['streamSettings', 'finalmask']}
network={network}
protocol={protocol}
form={form}
/>
{(() => {
const flow = (form.getFieldValue(['settings', 'flow']) ?? '') as string;
if (!isMuxAllowed(protocol, flow, network)) return null;