diff --git a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx
index af65ede0..6435ea48 100644
--- a/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx
+++ b/frontend/src/pages/xray/outbounds/OutboundFormModal.tsx
@@ -62,9 +62,8 @@ import {
newStreamSlice,
} from './outbound-form-helpers';
import { OutboundCoreProtocolFields } from './outbound-core-fields';
-import { OutboundOnlyProtocolFields } from './outbound-only-fields';
-import { FreedomOutboundFields } from './outbound-freedom-fields';
import { WireguardOutboundFields } from './outbound-wireguard-fields';
+import { BlackholeFields, DnsFields, FreedomFields, LoopbackFields } from './protocols';
import './OutboundFormModal.css';
// Pattern A rewrite of OutboundFormModal. Built as a sibling `.new.tsx`
@@ -391,9 +390,11 @@ export default function OutboundFormModal({
-
+ {protocol === 'loopback' && }
+ {protocol === 'blackhole' && }
+ {protocol === 'dns' && }
- {protocol === 'freedom' && }
+ {protocol === 'freedom' && }
{protocol === 'vless' && (
diff --git a/frontend/src/pages/xray/outbounds/outbound-only-fields.tsx b/frontend/src/pages/xray/outbounds/outbound-only-fields.tsx
deleted file mode 100644
index e491a796..00000000
--- a/frontend/src/pages/xray/outbounds/outbound-only-fields.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { Button, Form, Input, InputNumber, Select } from 'antd';
-import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
-
-import { DNSRuleActions } from '@/schemas/primitives';
-
-export function OutboundOnlyProtocolFields({ protocol }: { protocol: string }) {
- const { t } = useTranslation();
- return (
- <>
- {protocol === 'loopback' && (
-
-
-
- )}
-
- {protocol === 'blackhole' && (
-
-
-
- )}
-
- {protocol === 'dns' && (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- {(fields, { add, remove }) => (
- <>
-
- }
- onClick={() => add({ action: 'direct', qtype: '', domain: '' })}
- />
-
- {fields.map((field, index) => (
-
-
-
- {t('pages.xray.outboundForm.ruleN', { n: index + 1 })}
- remove(field.name)}
- />
-
-
-
-
-
-
-
-
-
-
-
- ))}
- >
- )}
-
- >
- )}
- >
- );
-}
diff --git a/frontend/src/pages/xray/outbounds/protocols/blackhole.tsx b/frontend/src/pages/xray/outbounds/protocols/blackhole.tsx
new file mode 100644
index 00000000..fb919af2
--- /dev/null
+++ b/frontend/src/pages/xray/outbounds/protocols/blackhole.tsx
@@ -0,0 +1,17 @@
+import { useTranslation } from 'react-i18next';
+import { Form, Select } from 'antd';
+
+export default function BlackholeFields() {
+ const { t } = useTranslation();
+ return (
+
+
+
+ );
+}
diff --git a/frontend/src/pages/xray/outbounds/protocols/dns.tsx b/frontend/src/pages/xray/outbounds/protocols/dns.tsx
new file mode 100644
index 00000000..85940d15
--- /dev/null
+++ b/frontend/src/pages/xray/outbounds/protocols/dns.tsx
@@ -0,0 +1,70 @@
+import { useTranslation } from 'react-i18next';
+import { Button, Form, Input, InputNumber, Select } from 'antd';
+import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
+
+import { DNSRuleActions } from '@/schemas/primitives';
+
+export default function DnsFields() {
+ const { t } = useTranslation();
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+
+ }
+ onClick={() => add({ action: 'direct', qtype: '', domain: '' })}
+ />
+
+ {fields.map((field, index) => (
+
+
+
+ {t('pages.xray.outboundForm.ruleN', { n: index + 1 })}
+ remove(field.name)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+ >
+ )}
+
+ >
+ );
+}
diff --git a/frontend/src/pages/xray/outbounds/outbound-freedom-fields.tsx b/frontend/src/pages/xray/outbounds/protocols/freedom.tsx
similarity index 99%
rename from frontend/src/pages/xray/outbounds/outbound-freedom-fields.tsx
rename to frontend/src/pages/xray/outbounds/protocols/freedom.tsx
index 4eb8604d..818cbffe 100644
--- a/frontend/src/pages/xray/outbounds/outbound-freedom-fields.tsx
+++ b/frontend/src/pages/xray/outbounds/protocols/freedom.tsx
@@ -5,7 +5,7 @@ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { OutboundDomainStrategies } from '@/schemas/primitives';
import type { OutboundFormValues } from '@/schemas/forms/outbound-form';
-export function FreedomOutboundFields({ form }: { form: FormInstance }) {
+export default function FreedomFields({ form }: { form: FormInstance }) {
const { t } = useTranslation();
return (
<>
diff --git a/frontend/src/pages/xray/outbounds/protocols/index.ts b/frontend/src/pages/xray/outbounds/protocols/index.ts
new file mode 100644
index 00000000..54b7e4e6
--- /dev/null
+++ b/frontend/src/pages/xray/outbounds/protocols/index.ts
@@ -0,0 +1,4 @@
+export { default as FreedomFields } from './freedom';
+export { default as LoopbackFields } from './loopback';
+export { default as BlackholeFields } from './blackhole';
+export { default as DnsFields } from './dns';
diff --git a/frontend/src/pages/xray/outbounds/protocols/loopback.tsx b/frontend/src/pages/xray/outbounds/protocols/loopback.tsx
new file mode 100644
index 00000000..d75e693c
--- /dev/null
+++ b/frontend/src/pages/xray/outbounds/protocols/loopback.tsx
@@ -0,0 +1,11 @@
+import { useTranslation } from 'react-i18next';
+import { Form, Input } from 'antd';
+
+export default function LoopbackFields() {
+ const { t } = useTranslation();
+ return (
+
+
+
+ );
+}