refactor(frontend): extract OutboundFormModal wireguard field block

OutboundFormModal.tsx 1753 -> 1622. Moved the wireguard protocol field block (address, keypair gen, domainStrategy, peers + allowedIPs) into outbound-wireguard-fields.tsx; dropped now-unused icon/InputAddon/WireguardDomainStrategy imports. Verbatim relocation; wireguard snapshot unchanged -> no behavior change. typecheck/lint/build green.
This commit is contained in:
MHSanaei 2026-05-30 16:52:13 +02:00
parent 2b02f1b745
commit c7917d12d3
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
2 changed files with 144 additions and 134 deletions

View file

@ -13,12 +13,9 @@ import {
Tabs, Tabs,
message, message,
} from 'antd'; } from 'antd';
import { DeleteOutlined, MinusOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
import { FinalMaskForm } from '@/lib/xray/forms/transport'; import { FinalMaskForm } from '@/lib/xray/forms/transport';
import { HeaderMapEditor } from '@/components/form'; import { HeaderMapEditor } from '@/components/form';
import { HysteriaMasqueradeForm } from '@/lib/xray/forms/protocols/shared'; import { HysteriaMasqueradeForm } from '@/lib/xray/forms/protocols/shared';
import { InputAddon } from '@/components/ui';
import { JsonEditor } from '@/components/form'; import { JsonEditor } from '@/components/form';
import { Wireguard } from '@/utils'; import { Wireguard } from '@/utils';
import { import {
@ -39,7 +36,6 @@ import {
DOMAIN_STRATEGY_OPTION, DOMAIN_STRATEGY_OPTION,
SNIFFING_OPTION, SNIFFING_OPTION,
TCP_CONGESTION_OPTION, TCP_CONGESTION_OPTION,
WireguardDomainStrategy,
} from '@/schemas/primitives'; } from '@/schemas/primitives';
import { import {
HappyEyeballsSchema, HappyEyeballsSchema,
@ -75,6 +71,7 @@ import {
} from './outbound-form-helpers'; } from './outbound-form-helpers';
import { OutboundOnlyProtocolFields } from './outbound-only-fields'; import { OutboundOnlyProtocolFields } from './outbound-only-fields';
import { FreedomOutboundFields } from './outbound-freedom-fields'; import { FreedomOutboundFields } from './outbound-freedom-fields';
import { WireguardOutboundFields } from './outbound-wireguard-fields';
import './OutboundFormModal.css'; import './OutboundFormModal.css';
// Pattern A rewrite of OutboundFormModal. Built as a sibling `.new.tsx` // Pattern A rewrite of OutboundFormModal. Built as a sibling `.new.tsx`
@ -582,136 +579,7 @@ export default function OutboundFormModal({
</Form.Item> </Form.Item>
)} )}
{protocol === 'wireguard' && ( {protocol === 'wireguard' && <WireguardOutboundFields form={form} />}
<>
<Form.Item label={t('pages.inbounds.address')} name={['settings', 'address']}>
<Input placeholder="comma-separated, e.g. 10.0.0.1,fd00::1" />
</Form.Item>
<Form.Item label={t('pages.inbounds.privatekey')}>
<Space.Compact block>
<Form.Item name={['settings', 'secretKey']} noStyle>
<Input style={{ width: 'calc(100% - 32px)' }} />
</Form.Item>
<Button
icon={<ReloadOutlined />}
onClick={() => {
const pair = Wireguard.generateKeypair();
form.setFieldValue(['settings', 'secretKey'], pair.privateKey);
form.setFieldValue(['settings', 'pubKey'], pair.publicKey);
}}
/>
</Space.Compact>
</Form.Item>
<Form.Item label={t('pages.inbounds.publicKey')} name={['settings', 'pubKey']}>
<Input disabled />
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.domainStrategy')} name={['settings', 'domainStrategy']}>
<Select
options={[
{ value: '', label: `(${t('none')})` },
...WireguardDomainStrategy.map((s) => ({ value: s, label: s })),
]}
/>
</Form.Item>
<Form.Item label="MTU" name={['settings', 'mtu']}>
<InputNumber min={0} />
</Form.Item>
<Form.Item label={t('pages.xray.outboundForm.workers')} name={['settings', 'workers']}>
<InputNumber min={0} />
</Form.Item>
<Form.Item
label={t('pages.inbounds.info.noKernelTun')}
name={['settings', 'noKernelTun']}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item label={t('pages.xray.outboundForm.reserved')} name={['settings', 'reserved']}>
<Input placeholder="comma-separated bytes, e.g. 1,2,3" />
</Form.Item>
<Form.List name={['settings', 'peers']}>
{(fields, { add, remove }) => (
<>
<Form.Item label={t('pages.inbounds.form.peers')}>
<Button
size="small"
type="primary"
icon={<PlusOutlined />}
onClick={() =>
add({
publicKey: '',
psk: '',
allowedIPs: ['0.0.0.0/0', '::/0'],
endpoint: '',
keepAlive: 0,
})
}
/>
</Form.Item>
{fields.map((field, index) => (
<div key={field.key}>
<Form.Item wrapperCol={{ md: { span: 14, offset: 8 } }}>
<div className="item-heading">
<span>{t('pages.inbounds.info.peerNumber', { n: index + 1 })}</span>
{fields.length > 1 && (
<DeleteOutlined
className="danger-icon"
onClick={() => remove(field.name)}
/>
)}
</div>
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.endpoint')} name={[field.name, 'endpoint']}>
<Input />
</Form.Item>
<Form.Item
label={t('pages.inbounds.publicKey')}
name={[field.name, 'publicKey']}
>
<Input />
</Form.Item>
<Form.Item label="PSK" name={[field.name, 'psk']}>
<Input />
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.allowedIPs')}>
<Form.List name={[field.name, 'allowedIPs']}>
{(ipFields, { add: addIp, remove: removeIp }) => (
<>
{ipFields.map((ipField, ipIdx) => (
<Space.Compact
key={ipField.key}
block
style={{ marginBottom: 4 }}
>
<Form.Item noStyle name={ipField.name}>
<Input />
</Form.Item>
{ipFields.length > 1 && (
<InputAddon onClick={() => removeIp(ipIdx)}>
<MinusOutlined />
</InputAddon>
)}
</Space.Compact>
))}
<Button
size="small"
icon={<PlusOutlined />}
onClick={() => addIp('')}
/>
</>
)}
</Form.List>
</Form.Item>
<Form.Item label={t('pages.inbounds.info.keepAlive')} name={[field.name, 'keepAlive']}>
<InputNumber min={0} />
</Form.Item>
</div>
))}
</>
)}
</Form.List>
</>
)}
{streamAllowed && network && ( {streamAllowed && network && (
<> <>

View file

@ -0,0 +1,142 @@
import { useTranslation } from 'react-i18next';
import { Button, Form, Input, InputNumber, Select, Space, Switch, type FormInstance } from 'antd';
import { DeleteOutlined, MinusOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
import { Wireguard } from '@/utils';
import { InputAddon } from '@/components/ui';
import { WireguardDomainStrategy } from '@/schemas/primitives';
import type { OutboundFormValues } from '@/schemas/forms/outbound-form';
export function WireguardOutboundFields({ form }: { form: FormInstance<OutboundFormValues> }) {
const { t } = useTranslation();
return (
<>
<Form.Item label={t('pages.inbounds.address')} name={['settings', 'address']}>
<Input placeholder="comma-separated, e.g. 10.0.0.1,fd00::1" />
</Form.Item>
<Form.Item label={t('pages.inbounds.privatekey')}>
<Space.Compact block>
<Form.Item name={['settings', 'secretKey']} noStyle>
<Input style={{ width: 'calc(100% - 32px)' }} />
</Form.Item>
<Button
icon={<ReloadOutlined />}
onClick={() => {
const pair = Wireguard.generateKeypair();
form.setFieldValue(['settings', 'secretKey'], pair.privateKey);
form.setFieldValue(['settings', 'pubKey'], pair.publicKey);
}}
/>
</Space.Compact>
</Form.Item>
<Form.Item label={t('pages.inbounds.publicKey')} name={['settings', 'pubKey']}>
<Input disabled />
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.domainStrategy')} name={['settings', 'domainStrategy']}>
<Select
options={[
{ value: '', label: `(${t('none')})` },
...WireguardDomainStrategy.map((s) => ({ value: s, label: s })),
]}
/>
</Form.Item>
<Form.Item label="MTU" name={['settings', 'mtu']}>
<InputNumber min={0} />
</Form.Item>
<Form.Item label={t('pages.xray.outboundForm.workers')} name={['settings', 'workers']}>
<InputNumber min={0} />
</Form.Item>
<Form.Item
label={t('pages.inbounds.info.noKernelTun')}
name={['settings', 'noKernelTun']}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item label={t('pages.xray.outboundForm.reserved')} name={['settings', 'reserved']}>
<Input placeholder="comma-separated bytes, e.g. 1,2,3" />
</Form.Item>
<Form.List name={['settings', 'peers']}>
{(fields, { add, remove }) => (
<>
<Form.Item label={t('pages.inbounds.form.peers')}>
<Button
size="small"
type="primary"
icon={<PlusOutlined />}
onClick={() =>
add({
publicKey: '',
psk: '',
allowedIPs: ['0.0.0.0/0', '::/0'],
endpoint: '',
keepAlive: 0,
})
}
/>
</Form.Item>
{fields.map((field, index) => (
<div key={field.key}>
<Form.Item wrapperCol={{ md: { span: 14, offset: 8 } }}>
<div className="item-heading">
<span>{t('pages.inbounds.info.peerNumber', { n: index + 1 })}</span>
{fields.length > 1 && (
<DeleteOutlined
className="danger-icon"
onClick={() => remove(field.name)}
/>
)}
</div>
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.endpoint')} name={[field.name, 'endpoint']}>
<Input />
</Form.Item>
<Form.Item
label={t('pages.inbounds.publicKey')}
name={[field.name, 'publicKey']}
>
<Input />
</Form.Item>
<Form.Item label="PSK" name={[field.name, 'psk']}>
<Input />
</Form.Item>
<Form.Item label={t('pages.xray.wireguard.allowedIPs')}>
<Form.List name={[field.name, 'allowedIPs']}>
{(ipFields, { add: addIp, remove: removeIp }) => (
<>
{ipFields.map((ipField, ipIdx) => (
<Space.Compact
key={ipField.key}
block
style={{ marginBottom: 4 }}
>
<Form.Item noStyle name={ipField.name}>
<Input />
</Form.Item>
{ipFields.length > 1 && (
<InputAddon onClick={() => removeIp(ipIdx)}>
<MinusOutlined />
</InputAddon>
)}
</Space.Compact>
))}
<Button
size="small"
icon={<PlusOutlined />}
onClick={() => addIp('')}
/>
</>
)}
</Form.List>
</Form.Item>
<Form.Item label={t('pages.inbounds.info.keepAlive')} name={[field.name, 'keepAlive']}>
<InputNumber min={0} />
</Form.Item>
</div>
))}
</>
)}
</Form.List>
</>
);
}