mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-28 16:09:36 +00:00
feat(frontend): protocol tab Shadowsocks section (Pattern A)
Adds the Shadowsocks sub-form: method picker (from SSMethodSchema's seven schema-aligned options), conditional password input gated on isSS2022, network picker (tcp/udp/tcp,udp), ivCheck toggle. Method change cascades through the Select's onChange — regenerating the inbound-level password via RandomUtil.randomShadowsocksPassword. The shadowsockses[] multi-user list reset is deferred until the clients-management section lands. Uses isSS2022 from lib/xray/protocol-capabilities to gate the password field exactly the way the legacy modal did — keeps the form behavior identical without referencing the legacy class. SSMethodSchema.options drives the Select rather than the legacy SSMethods const (which the inbound modal pulled from models/inbound.ts). This commits to the schema-aligned 7-entry list for inbound; the outbound divergence (9 entries with legacy aliases) is still pending in OutboundFormModal — defer the UX decision to that rewrite.
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
Typography,
|
||||
message,
|
||||
} from 'antd';
|
||||
import { SyncOutlined } from '@ant-design/icons';
|
||||
|
||||
import { HttpUtil, NumberFormatter, RandomUtil, SizeFormatter } from '@/utils';
|
||||
import {
|
||||
@@ -23,6 +24,8 @@ import {
|
||||
formValuesToWirePayload,
|
||||
} from '@/lib/xray/inbound-form-adapter';
|
||||
import { createDefaultInboundSettings } from '@/lib/xray/inbound-defaults';
|
||||
import { isSS2022 } from '@/lib/xray/protocol-capabilities';
|
||||
import { SSMethodSchema } from '@/schemas/protocols/inbound/shadowsocks';
|
||||
import {
|
||||
InboundFormBaseSchema,
|
||||
InboundFormSchema,
|
||||
@@ -95,6 +98,11 @@ export default function InboundFormModalNew({
|
||||
const isNodeEligible = NODE_ELIGIBLE_PROTOCOLS.has(protocol);
|
||||
const sniffingEnabled = Form.useWatch(['sniffing', 'enabled'], form) ?? false;
|
||||
const vlessEncryption = Form.useWatch(['settings', 'encryption'], form) ?? '';
|
||||
const ssMethod = Form.useWatch(['settings', 'method'], form);
|
||||
const isSSWith2022 = isSS2022({
|
||||
protocol,
|
||||
settings: typeof ssMethod === 'string' ? { method: ssMethod } : {},
|
||||
});
|
||||
|
||||
const matchesVlessAuth = (
|
||||
block: { id?: string; label?: string } | undefined | null,
|
||||
@@ -326,6 +334,61 @@ export default function InboundFormModalNew({
|
||||
|
||||
const protocolTab = (
|
||||
<>
|
||||
{protocol === Protocols.SHADOWSOCKS && (
|
||||
<>
|
||||
<Form.Item name={['settings', 'method']} label="Encryption method">
|
||||
<Select
|
||||
onChange={(v) => {
|
||||
form.setFieldValue(
|
||||
['settings', 'password'],
|
||||
RandomUtil.randomShadowsocksPassword(v as string),
|
||||
);
|
||||
}}
|
||||
>
|
||||
{SSMethodSchema.options.map((m) => (
|
||||
<Select.Option key={m} value={m}>{m}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{isSSWith2022 && (
|
||||
<Form.Item
|
||||
name={['settings', 'password']}
|
||||
label={
|
||||
<>
|
||||
Password{' '}
|
||||
<SyncOutlined
|
||||
className="random-icon"
|
||||
onClick={() => {
|
||||
const method = form.getFieldValue(['settings', 'method']);
|
||||
form.setFieldValue(
|
||||
['settings', 'password'],
|
||||
RandomUtil.randomShadowsocksPassword(method as string),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item name={['settings', 'network']} label="Network">
|
||||
<Select style={{ width: 120 }}>
|
||||
<Select.Option value="tcp,udp">TCP, UDP</Select.Option>
|
||||
<Select.Option value="tcp">TCP</Select.Option>
|
||||
<Select.Option value="udp">UDP</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['settings', 'ivCheck']}
|
||||
label="ivCheck"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
|
||||
{protocol === Protocols.VLESS && (
|
||||
<>
|
||||
<Form.Item name={['settings', 'decryption']} label={t('pages.inbounds.decryption')}>
|
||||
@@ -437,7 +500,7 @@ export default function InboundFormModalNew({
|
||||
>
|
||||
<Tabs items={[
|
||||
{ key: 'basic', label: t('pages.xray.basicTemplate'), children: basicTab },
|
||||
...(protocol === Protocols.VLESS
|
||||
...(protocol === Protocols.VLESS || protocol === Protocols.SHADOWSOCKS
|
||||
? [{ key: 'protocol', label: t('pages.inbounds.protocol'), children: protocolTab }]
|
||||
: []),
|
||||
{ key: 'sniffing', label: t('pages.inbounds.sniffingTab'), children: sniffingTab },
|
||||
|
||||
Reference in New Issue
Block a user