mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 13:14:11 +00:00
refactor(frontend): fold HysteriaMasqueradeForm into the hysteria forms
Inline the masquerade fields directly into both hysteria transport forms (inbounds/form/protocols/hysteria + xray/outbounds/transport/hysteria) and delete the shared lib/xray/forms/transport/HysteriaMasqueradeForm so each hysteria form is self-contained. The masquerade JSX is unchanged; form is typed as the untyped FormInstance (as the shared component was) so the masquerade name paths still resolve. No behavior change.
This commit is contained in:
parent
8a34eeedc9
commit
8cddff2c41
4 changed files with 213 additions and 131 deletions
|
|
@ -1,120 +0,0 @@
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { Form, Input, InputNumber, Select, Switch } from 'antd';
|
||||
import type { FormInstance } from 'antd';
|
||||
|
||||
import { HeaderMapEditor } from '@/components/form';
|
||||
|
||||
const MASQ_PATH = ['streamSettings', 'hysteriaSettings', 'masquerade'];
|
||||
|
||||
interface HysteriaMasqueradeFormProps {
|
||||
form: FormInstance;
|
||||
}
|
||||
|
||||
export default function HysteriaMasqueradeForm({ form }: HysteriaMasqueradeFormProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Form.Item label={t('pages.inbounds.form.masquerade')}>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH);
|
||||
return (
|
||||
<Switch
|
||||
checked={!!m}
|
||||
onChange={(checked) =>
|
||||
form.setFieldValue(
|
||||
MASQ_PATH,
|
||||
checked
|
||||
? {
|
||||
type: '', dir: '', url: '',
|
||||
rewriteHost: false, insecure: false,
|
||||
content: '', headers: {}, statusCode: 0,
|
||||
}
|
||||
: undefined,
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH) as { type?: string } | undefined;
|
||||
if (!m) return null;
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.type')}
|
||||
name={[...MASQ_PATH, 'type']}
|
||||
>
|
||||
<Select
|
||||
options={[
|
||||
{ value: '', label: 'default (404 page)' },
|
||||
{ value: 'proxy', label: 'proxy (reverse proxy)' },
|
||||
{ value: 'file', label: 'file (serve directory)' },
|
||||
{ value: 'string', label: 'string (fixed body)' },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{m.type === 'proxy' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.upstreamUrl')}
|
||||
name={[...MASQ_PATH, 'url']}
|
||||
>
|
||||
<Input placeholder="https://www.example.com" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.rewriteHost')}
|
||||
name={[...MASQ_PATH, 'rewriteHost']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.skipTlsVerify')}
|
||||
name={[...MASQ_PATH, 'insecure']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{m.type === 'file' && (
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.directory')}
|
||||
name={[...MASQ_PATH, 'dir']}
|
||||
>
|
||||
<Input placeholder="/var/www/html" />
|
||||
</Form.Item>
|
||||
)}
|
||||
{m.type === 'string' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.statusCode')}
|
||||
name={[...MASQ_PATH, 'statusCode']}
|
||||
>
|
||||
<InputNumber min={0} max={599} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.body')}
|
||||
name={[...MASQ_PATH, 'content']}
|
||||
>
|
||||
<Input.TextArea autoSize={{ minRows: 3 }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.headers')}
|
||||
name={[...MASQ_PATH, 'headers']}
|
||||
>
|
||||
<HeaderMapEditor mode="v1" />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,2 +1 @@
|
|||
export { default as FinalMaskForm } from './FinalMaskForm';
|
||||
export { default as HysteriaMasqueradeForm } from './HysteriaMasqueradeForm';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { Form, InputNumber, type FormInstance } from 'antd';
|
||||
import { Form, Input, InputNumber, Select, Switch, type FormInstance } from 'antd';
|
||||
|
||||
import { HysteriaMasqueradeForm } from '@/lib/xray/forms/transport';
|
||||
import type { InboundFormValues } from '@/schemas/forms/inbound-form';
|
||||
import { HeaderMapEditor } from '@/components/form';
|
||||
|
||||
export default function HysteriaFields({ form }: { form: FormInstance<InboundFormValues> }) {
|
||||
const MASQ_PATH = ['streamSettings', 'hysteriaSettings', 'masquerade'];
|
||||
|
||||
export default function HysteriaFields({ form }: { form: FormInstance }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
|
|
@ -21,7 +22,107 @@ export default function HysteriaFields({ form }: { form: FormInstance<InboundFor
|
|||
<InputNumber min={1} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
|
||||
<HysteriaMasqueradeForm form={form} />
|
||||
<Form.Item label={t('pages.inbounds.form.masquerade')}>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH);
|
||||
return (
|
||||
<Switch
|
||||
checked={!!m}
|
||||
onChange={(checked) =>
|
||||
form.setFieldValue(
|
||||
MASQ_PATH,
|
||||
checked
|
||||
? {
|
||||
type: '', dir: '', url: '',
|
||||
rewriteHost: false, insecure: false,
|
||||
content: '', headers: {}, statusCode: 0,
|
||||
}
|
||||
: undefined,
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH) as { type?: string } | undefined;
|
||||
if (!m) return null;
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.type')}
|
||||
name={[...MASQ_PATH, 'type']}
|
||||
>
|
||||
<Select
|
||||
options={[
|
||||
{ value: '', label: 'default (404 page)' },
|
||||
{ value: 'proxy', label: 'proxy (reverse proxy)' },
|
||||
{ value: 'file', label: 'file (serve directory)' },
|
||||
{ value: 'string', label: 'string (fixed body)' },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{m.type === 'proxy' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.upstreamUrl')}
|
||||
name={[...MASQ_PATH, 'url']}
|
||||
>
|
||||
<Input placeholder="https://www.example.com" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.rewriteHost')}
|
||||
name={[...MASQ_PATH, 'rewriteHost']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.skipTlsVerify')}
|
||||
name={[...MASQ_PATH, 'insecure']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{m.type === 'file' && (
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.directory')}
|
||||
name={[...MASQ_PATH, 'dir']}
|
||||
>
|
||||
<Input placeholder="/var/www/html" />
|
||||
</Form.Item>
|
||||
)}
|
||||
{m.type === 'string' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.statusCode')}
|
||||
name={[...MASQ_PATH, 'statusCode']}
|
||||
>
|
||||
<InputNumber min={0} max={599} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.body')}
|
||||
name={[...MASQ_PATH, 'content']}
|
||||
>
|
||||
<Input.TextArea autoSize={{ minRows: 3 }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.headers')}
|
||||
name={[...MASQ_PATH, 'headers']}
|
||||
>
|
||||
<HeaderMapEditor mode="v1" />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { useTranslation } from 'react-i18next';
|
||||
import { Form, Input, InputNumber, type FormInstance } from 'antd';
|
||||
import { Form, Input, InputNumber, Select, Switch, type FormInstance } from 'antd';
|
||||
|
||||
import { HysteriaMasqueradeForm } from '@/lib/xray/forms/transport';
|
||||
import type { OutboundFormValues } from '@/schemas/forms/outbound-form';
|
||||
import { HeaderMapEditor } from '@/components/form';
|
||||
|
||||
export default function HysteriaForm({ form }: { form: FormInstance<OutboundFormValues> }) {
|
||||
const MASQ_PATH = ['streamSettings', 'hysteriaSettings', 'masquerade'];
|
||||
|
||||
export default function HysteriaForm({ form }: { form: FormInstance }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
|
|
@ -26,7 +27,108 @@ export default function HysteriaForm({ form }: { form: FormInstance<OutboundForm
|
|||
>
|
||||
<InputNumber min={1} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<HysteriaMasqueradeForm form={form} />
|
||||
|
||||
<Form.Item label={t('pages.inbounds.form.masquerade')}>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH);
|
||||
return (
|
||||
<Switch
|
||||
checked={!!m}
|
||||
onChange={(checked) =>
|
||||
form.setFieldValue(
|
||||
MASQ_PATH,
|
||||
checked
|
||||
? {
|
||||
type: '', dir: '', url: '',
|
||||
rewriteHost: false, insecure: false,
|
||||
content: '', headers: {}, statusCode: 0,
|
||||
}
|
||||
: undefined,
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => {
|
||||
const m = form.getFieldValue(MASQ_PATH) as { type?: string } | undefined;
|
||||
if (!m) return null;
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.type')}
|
||||
name={[...MASQ_PATH, 'type']}
|
||||
>
|
||||
<Select
|
||||
options={[
|
||||
{ value: '', label: 'default (404 page)' },
|
||||
{ value: 'proxy', label: 'proxy (reverse proxy)' },
|
||||
{ value: 'file', label: 'file (serve directory)' },
|
||||
{ value: 'string', label: 'string (fixed body)' },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{m.type === 'proxy' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.upstreamUrl')}
|
||||
name={[...MASQ_PATH, 'url']}
|
||||
>
|
||||
<Input placeholder="https://www.example.com" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.rewriteHost')}
|
||||
name={[...MASQ_PATH, 'rewriteHost']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.skipTlsVerify')}
|
||||
name={[...MASQ_PATH, 'insecure']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{m.type === 'file' && (
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.directory')}
|
||||
name={[...MASQ_PATH, 'dir']}
|
||||
>
|
||||
<Input placeholder="/var/www/html" />
|
||||
</Form.Item>
|
||||
)}
|
||||
{m.type === 'string' && (
|
||||
<>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.statusCode')}
|
||||
name={[...MASQ_PATH, 'statusCode']}
|
||||
>
|
||||
<InputNumber min={0} max={599} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.body')}
|
||||
name={[...MASQ_PATH, 'content']}
|
||||
>
|
||||
<Input.TextArea autoSize={{ minRows: 3 }} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.headers')}
|
||||
name={[...MASQ_PATH, 'headers']}
|
||||
>
|
||||
<HeaderMapEditor mode="v1" />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue