fix(outbounds): prevent freedom save crash, complete its fields (#4686)

freedomToWire called Object.entries(s.fragment), but getFieldsValue(true)
returns freedom settings without a fragment object when the Fragment switch
is off (its sub-fields never register). That threw 'Cannot convert undefined
or null to object' and silently killed the save. Guard fragment with a
fallback so an unset value is treated as empty.

While verifying against xray-core's freedom config, also:
- add the missing userLevel field (schema, form schema, adapter, UI)
- fix noise applyTo enum to ip/ipv4/ipv6 (xray rejects the old host/all)

Closes #4686
This commit is contained in:
MHSanaei
2026-05-31 19:50:50 +02:00
parent c20ee00fa3
commit f02018cfb7
5 changed files with 39 additions and 4 deletions
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next';
import { Button, Form, Input, Select, Switch, type FormInstance } from 'antd';
import { Button, Form, Input, InputNumber, Select, Switch, type FormInstance } from 'antd';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { OutboundDomainStrategies } from '@/schemas/primitives';
@@ -20,6 +20,9 @@ export default function FreedomFields({ form }: { form: FormInstance<OutboundFor
<Form.Item label={t('pages.xray.outboundForm.redirect')} name={['settings', 'redirect']}>
<Input />
</Form.Item>
<Form.Item label={t('pages.xray.tun.userLevel')} name={['settings', 'userLevel']}>
<InputNumber min={0} style={{ width: '100%' }} />
</Form.Item>
<Form.Item label={t('pages.xray.outboundForm.proxyProtocol')} name={['settings', 'proxyProtocol']}>
<Select
options={[