refactor(frontend): split inbound-only protocol forms (tun, tunnel) into per-file

Extract the tun and tunnel protocol blocks from InboundFormModal into inbounds/form/protocols/{tun,tunnel}.tsx (presentational, declarative). First inbound-side per-protocol split. Verbatim relocation; inbound snapshots unchanged -> no behavior change. typecheck/lint/build green.
This commit is contained in:
MHSanaei 2026-05-30 18:18:44 +02:00
parent d40f6b9831
commit afd44ed687
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
4 changed files with 135 additions and 115 deletions

View file

@ -84,6 +84,7 @@ import { InputAddon } from '@/components/ui';
import './InboundFormModal.css'; import './InboundFormModal.css';
import { AdvancedAllEditor, AdvancedSliceEditor } from './advanced-editors'; import { AdvancedAllEditor, AdvancedSliceEditor } from './advanced-editors';
import { TunFields, TunnelFields } from './protocols';
const { TextArea } = Input; const { TextArea } = Input;
import { coerceInboundJsonField, type DBInbound } from '@/models/dbinbound'; import { coerceInboundJsonField, type DBInbound } from '@/models/dbinbound';
@ -1053,122 +1054,9 @@ export default function InboundFormModal({
</> </>
)} )}
{protocol === Protocols.TUN && ( {protocol === Protocols.TUN && <TunFields />}
<>
<Form.Item name={['settings', 'name']} label={t('pages.inbounds.info.interfaceName')}>
<Input placeholder="xray0" />
</Form.Item>
<Form.Item name={['settings', 'mtu']} label="MTU">
<InputNumber min={0} />
</Form.Item>
<Form.List name={['settings', 'gateway']}>
{(fields, { add, remove }) => (
<Form.Item label={t('pages.inbounds.info.gateway')}>
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '10.0.0.1/16' : 'fc00::1/64'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.List name={['settings', 'dns']}>
{(fields, { add, remove }) => (
<Form.Item label="DNS">
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '1.1.1.1' : '8.8.8.8'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.Item name={['settings', 'userLevel']} label={t('pages.xray.tun.userLevel')}>
<InputNumber min={0} />
</Form.Item>
<Form.List name={['settings', 'autoSystemRoutingTable']}>
{(fields, { add, remove }) => (
<Form.Item
label={
<Tooltip title={t('pages.inbounds.form.autoSystemRoutesTooltip')}>
{t('pages.inbounds.info.autoSystemRoutes')}
</Tooltip>
}
>
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '0.0.0.0/0' : '::/0'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.Item
name={['settings', 'autoOutboundsInterface']}
label={
<Tooltip title={t('pages.inbounds.form.autoOutboundsInterfaceTooltip')}>
{t('pages.inbounds.form.autoOutboundsInterface')}
</Tooltip>
}
>
<Input placeholder="auto" />
</Form.Item>
</>
)}
{protocol === Protocols.TUNNEL && ( {protocol === Protocols.TUNNEL && <TunnelFields />}
<>
<Form.Item name={['settings', 'rewriteAddress']} label={t('pages.inbounds.form.rewriteAddress')}>
<Input />
</Form.Item>
<Form.Item name={['settings', 'rewritePort']} label={t('pages.inbounds.form.rewritePort')}>
<InputNumber min={0} max={65535} />
</Form.Item>
<Form.Item name={['settings', 'allowedNetwork']} label={t('pages.inbounds.form.allowedNetwork')}>
<Select
options={[
{ value: 'tcp,udp', label: 'TCP, UDP' },
{ value: 'tcp', label: 'TCP' },
{ value: 'udp', label: 'UDP' },
]}
/>
</Form.Item>
<Form.Item label={t('pages.inbounds.portMap')} name={['settings', 'portMap']}>
<HeaderMapEditor mode="v1" />
</Form.Item>
<Form.Item
name={['settings', 'followRedirect']}
label={t('pages.inbounds.form.followRedirect')}
valuePropName="checked"
>
<Switch />
</Form.Item>
</>
)}
{(protocol === Protocols.HTTP || protocol === Protocols.MIXED) && ( {(protocol === Protocols.HTTP || protocol === Protocols.MIXED) && (
<> <>

View file

@ -0,0 +1,2 @@
export { default as TunFields } from './tun';
export { default as TunnelFields } from './tunnel';

View file

@ -0,0 +1,93 @@
import { useTranslation } from 'react-i18next';
import { Button, Form, Input, InputNumber, Space, Tooltip } from 'antd';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
export default function TunFields() {
const { t } = useTranslation();
return (
<>
<Form.Item name={['settings', 'name']} label={t('pages.inbounds.info.interfaceName')}>
<Input placeholder="xray0" />
</Form.Item>
<Form.Item name={['settings', 'mtu']} label="MTU">
<InputNumber min={0} />
</Form.Item>
<Form.List name={['settings', 'gateway']}>
{(fields, { add, remove }) => (
<Form.Item label={t('pages.inbounds.info.gateway')}>
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '10.0.0.1/16' : 'fc00::1/64'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.List name={['settings', 'dns']}>
{(fields, { add, remove }) => (
<Form.Item label="DNS">
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '1.1.1.1' : '8.8.8.8'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.Item name={['settings', 'userLevel']} label={t('pages.xray.tun.userLevel')}>
<InputNumber min={0} />
</Form.Item>
<Form.List name={['settings', 'autoSystemRoutingTable']}>
{(fields, { add, remove }) => (
<Form.Item
label={
<Tooltip title={t('pages.inbounds.form.autoSystemRoutesTooltip')}>
{t('pages.inbounds.info.autoSystemRoutes')}
</Tooltip>
}
>
<Button size="small" onClick={() => add('')}>
<PlusOutlined />
</Button>
{fields.map((field, j) => (
<Space.Compact key={field.key} block className="mt-4">
<Form.Item name={field.name} noStyle>
<Input placeholder={j === 0 ? '0.0.0.0/0' : '::/0'} />
</Form.Item>
<Button size="small" onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Space.Compact>
))}
</Form.Item>
)}
</Form.List>
<Form.Item
name={['settings', 'autoOutboundsInterface']}
label={
<Tooltip title={t('pages.inbounds.form.autoOutboundsInterfaceTooltip')}>
{t('pages.inbounds.form.autoOutboundsInterface')}
</Tooltip>
}
>
<Input placeholder="auto" />
</Form.Item>
</>
);
}

View file

@ -0,0 +1,37 @@
import { useTranslation } from 'react-i18next';
import { Form, Input, InputNumber, Select, Switch } from 'antd';
import { HeaderMapEditor } from '@/components/form';
export default function TunnelFields() {
const { t } = useTranslation();
return (
<>
<Form.Item name={['settings', 'rewriteAddress']} label={t('pages.inbounds.form.rewriteAddress')}>
<Input />
</Form.Item>
<Form.Item name={['settings', 'rewritePort']} label={t('pages.inbounds.form.rewritePort')}>
<InputNumber min={0} max={65535} />
</Form.Item>
<Form.Item name={['settings', 'allowedNetwork']} label={t('pages.inbounds.form.allowedNetwork')}>
<Select
options={[
{ value: 'tcp,udp', label: 'TCP, UDP' },
{ value: 'tcp', label: 'TCP' },
{ value: 'udp', label: 'UDP' },
]}
/>
</Form.Item>
<Form.Item label={t('pages.inbounds.portMap')} name={['settings', 'portMap']}>
<HeaderMapEditor mode="v1" />
</Form.Item>
<Form.Item
name={['settings', 'followRedirect']}
label={t('pages.inbounds.form.followRedirect')}
valuePropName="checked"
>
<Switch />
</Form.Item>
</>
);
}