diff --git a/frontend/src/pages/inbounds/form/InboundFormModal.tsx b/frontend/src/pages/inbounds/form/InboundFormModal.tsx
index fe602d29..571a7286 100644
--- a/frontend/src/pages/inbounds/form/InboundFormModal.tsx
+++ b/frontend/src/pages/inbounds/form/InboundFormModal.tsx
@@ -5,7 +5,6 @@ import {
Button,
Card,
Checkbox,
- Divider,
Empty,
Form,
Input,
@@ -41,7 +40,6 @@ import {
canEnableTls,
isSS2022,
} from '@/lib/xray/protocol-capabilities';
-import { SSMethodSchema } from '@/schemas/protocols/shared/shadowsocks';
import { getRandomRealityTarget } from '@/models/reality-targets';
import {
InboundFormBaseSchema,
@@ -84,7 +82,7 @@ import { InputAddon } from '@/components/ui';
import './InboundFormModal.css';
import { AdvancedAllEditor, AdvancedSliceEditor } from './advanced-editors';
-import { TunFields, TunnelFields } from './protocols';
+import { ShadowsocksFields, TunFields, TunnelFields, WireguardFields } from './protocols';
const { TextArea } = Input;
import { coerceInboundJsonField, type DBInbound } from '@/models/dbinbound';
@@ -948,111 +946,7 @@ export default function InboundFormModal({
const protocolTab = (
<>
- {protocol === Protocols.WIREGUARD && (
- <>
-
-
-
-
-
- } onClick={regenInboundWg} />
-
-
-
-
-
-
-
-
-
-
-
-
- {(fields, { add, remove }) => (
- <>
-
-
-
- {fields.map((field, idx) => (
-
- ))}
- >
- )}
-
- >
- )}
+ {protocol === Protocols.WIREGUARD && }
{protocol === Protocols.TUN && }
@@ -1131,57 +1025,7 @@ export default function InboundFormModal({
>
)}
- {protocol === Protocols.SHADOWSOCKS && (
- <>
-
-
- {isSSWith2022 && (
-
-
-
-
-
- }
- onClick={() => {
- const method = form.getFieldValue(['settings', 'method']);
- form.setFieldValue(
- ['settings', 'password'],
- RandomUtil.randomShadowsocksPassword(method as string),
- );
- }}
- />
-
-
- )}
-
-
-
-
-
-
- >
- )}
+ {protocol === Protocols.SHADOWSOCKS && }
{protocol === Protocols.VLESS && (
<>
diff --git a/frontend/src/pages/inbounds/form/protocols/index.ts b/frontend/src/pages/inbounds/form/protocols/index.ts
index a86f59db..f44af7eb 100644
--- a/frontend/src/pages/inbounds/form/protocols/index.ts
+++ b/frontend/src/pages/inbounds/form/protocols/index.ts
@@ -1,2 +1,4 @@
export { default as TunFields } from './tun';
export { default as TunnelFields } from './tunnel';
+export { default as ShadowsocksFields } from './shadowsocks';
+export { default as WireguardFields } from './wireguard';
diff --git a/frontend/src/pages/inbounds/form/protocols/shadowsocks.tsx b/frontend/src/pages/inbounds/form/protocols/shadowsocks.tsx
new file mode 100644
index 00000000..d18b815e
--- /dev/null
+++ b/frontend/src/pages/inbounds/form/protocols/shadowsocks.tsx
@@ -0,0 +1,67 @@
+import { useTranslation } from 'react-i18next';
+import { Button, Form, Input, Select, Space, Switch, type FormInstance } from 'antd';
+import { ReloadOutlined } from '@ant-design/icons';
+
+import { RandomUtil } from '@/utils';
+import { SSMethodSchema } from '@/schemas/protocols/shared/shadowsocks';
+import type { InboundFormValues } from '@/schemas/forms/inbound-form';
+
+interface ShadowsocksFieldsProps {
+ form: FormInstance;
+ isSSWith2022: boolean;
+}
+
+export default function ShadowsocksFields({ form, isSSWith2022 }: ShadowsocksFieldsProps) {
+ const { t } = useTranslation();
+ return (
+ <>
+
+
+ {isSSWith2022 && (
+
+
+
+
+
+ }
+ onClick={() => {
+ const method = form.getFieldValue(['settings', 'method']);
+ form.setFieldValue(
+ ['settings', 'password'],
+ RandomUtil.randomShadowsocksPassword(method as string),
+ );
+ }}
+ />
+
+
+ )}
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/pages/inbounds/form/protocols/wireguard.tsx b/frontend/src/pages/inbounds/form/protocols/wireguard.tsx
new file mode 100644
index 00000000..d646dd94
--- /dev/null
+++ b/frontend/src/pages/inbounds/form/protocols/wireguard.tsx
@@ -0,0 +1,120 @@
+import { useTranslation } from 'react-i18next';
+import { Button, Divider, Form, Input, InputNumber, Space, Switch } from 'antd';
+import { MinusOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
+
+import { Wireguard } from '@/utils';
+
+interface WireguardFieldsProps {
+ wgPubKey: string;
+ regenInboundWg: () => void;
+ regenWgPeerKeypair: (name: number) => void;
+}
+
+export default function WireguardFields({ wgPubKey, regenInboundWg, regenWgPeerKeypair }: WireguardFieldsProps) {
+ const { t } = useTranslation();
+ return (
+ <>
+
+
+
+
+
+ } onClick={regenInboundWg} />
+
+
+
+
+
+
+
+
+
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+
+
+
+ {fields.map((field, idx) => (
+
+ ))}
+ >
+ )}
+
+ >
+ );
+}