mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 12:44:22 +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:
parent
102465f9d1
commit
591a03ff96
1 changed files with 64 additions and 1 deletions
|
|
@ -16,6 +16,7 @@ import {
|
||||||
Typography,
|
Typography,
|
||||||
message,
|
message,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
|
import { SyncOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import { HttpUtil, NumberFormatter, RandomUtil, SizeFormatter } from '@/utils';
|
import { HttpUtil, NumberFormatter, RandomUtil, SizeFormatter } from '@/utils';
|
||||||
import {
|
import {
|
||||||
|
|
@ -23,6 +24,8 @@ import {
|
||||||
formValuesToWirePayload,
|
formValuesToWirePayload,
|
||||||
} from '@/lib/xray/inbound-form-adapter';
|
} from '@/lib/xray/inbound-form-adapter';
|
||||||
import { createDefaultInboundSettings } from '@/lib/xray/inbound-defaults';
|
import { createDefaultInboundSettings } from '@/lib/xray/inbound-defaults';
|
||||||
|
import { isSS2022 } from '@/lib/xray/protocol-capabilities';
|
||||||
|
import { SSMethodSchema } from '@/schemas/protocols/inbound/shadowsocks';
|
||||||
import {
|
import {
|
||||||
InboundFormBaseSchema,
|
InboundFormBaseSchema,
|
||||||
InboundFormSchema,
|
InboundFormSchema,
|
||||||
|
|
@ -95,6 +98,11 @@ export default function InboundFormModalNew({
|
||||||
const isNodeEligible = NODE_ELIGIBLE_PROTOCOLS.has(protocol);
|
const isNodeEligible = NODE_ELIGIBLE_PROTOCOLS.has(protocol);
|
||||||
const sniffingEnabled = Form.useWatch(['sniffing', 'enabled'], form) ?? false;
|
const sniffingEnabled = Form.useWatch(['sniffing', 'enabled'], form) ?? false;
|
||||||
const vlessEncryption = Form.useWatch(['settings', 'encryption'], form) ?? '';
|
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 = (
|
const matchesVlessAuth = (
|
||||||
block: { id?: string; label?: string } | undefined | null,
|
block: { id?: string; label?: string } | undefined | null,
|
||||||
|
|
@ -326,6 +334,61 @@ export default function InboundFormModalNew({
|
||||||
|
|
||||||
const protocolTab = (
|
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 && (
|
{protocol === Protocols.VLESS && (
|
||||||
<>
|
<>
|
||||||
<Form.Item name={['settings', 'decryption']} label={t('pages.inbounds.decryption')}>
|
<Form.Item name={['settings', 'decryption']} label={t('pages.inbounds.decryption')}>
|
||||||
|
|
@ -437,7 +500,7 @@ export default function InboundFormModalNew({
|
||||||
>
|
>
|
||||||
<Tabs items={[
|
<Tabs items={[
|
||||||
{ key: 'basic', label: t('pages.xray.basicTemplate'), children: basicTab },
|
{ 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: 'protocol', label: t('pages.inbounds.protocol'), children: protocolTab }]
|
||||||
: []),
|
: []),
|
||||||
{ key: 'sniffing', label: t('pages.inbounds.sniffingTab'), children: sniffingTab },
|
{ key: 'sniffing', label: t('pages.inbounds.sniffingTab'), children: sniffingTab },
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue