feat(xray): add connIdle and bufferSize policy controls

Expose level-0 connection policies in the panel's Basics tab: idle timeout (connIdle) and per-connection buffer size (bufferSize). Empty fields delete the key so Xray falls back to its own defaults. Adds en-US/fa-IR strings and types policy.levels in the Zod schema.
This commit is contained in:
MHSanaei
2026-06-03 21:52:37 +02:00
parent 1a64d7e9de
commit ceef413dc4
4 changed files with 78 additions and 1 deletions

View File

@@ -1,8 +1,9 @@
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Alert, Button, Input, Modal, Select, Space, Switch, Tabs } from 'antd';
import { Alert, Button, Input, InputNumber, Modal, Select, Space, Switch, Tabs } from 'antd';
import {
BarChartOutlined,
ClockCircleOutlined,
FileTextOutlined,
ReloadOutlined,
SettingOutlined,
@@ -54,6 +55,20 @@ export default function BasicsTab({
[setTemplateSettings],
);
const setLevel0 = useCallback(
(field: string, value: number | null) => mutate((tt) => {
if (!tt.policy) tt.policy = {};
if (!tt.policy.levels) tt.policy.levels = {};
if (!tt.policy.levels['0']) tt.policy.levels['0'] = {};
if (value === null || value === undefined) {
delete tt.policy.levels['0'][field];
} else {
tt.policy.levels['0'][field] = value;
}
}),
[mutate],
);
function confirmResetDefault() {
modal.confirm({
title: t('pages.settings.resetDefaultConfig'),
@@ -72,6 +87,7 @@ export default function BasicsTab({
const routingStrategy = templateSettings?.routing?.domainStrategy ?? 'AsIs';
const log = (templateSettings?.log || {}) as Record<string, unknown>;
const policy = (templateSettings?.policy?.system || {}) as Record<string, boolean>;
const level0 = (templateSettings?.policy?.levels?.['0'] || {}) as Record<string, unknown>;
const items = [
{
@@ -168,6 +184,50 @@ export default function BasicsTab({
</>
),
},
{
key: 'connection',
label: catTabLabel(<ClockCircleOutlined />, t('pages.xray.connectionLimits'), isMobile),
children: (
<>
<Alert
type="warning"
showIcon
className="mb-12 hint-alert"
title={t('pages.xray.connectionLimitsDesc')}
/>
<SettingListItem
title={t('pages.xray.connIdle')}
description={t('pages.xray.connIdleDesc')}
paddings="small"
control={
<InputNumber
value={typeof level0.connIdle === 'number' ? level0.connIdle : undefined}
min={0}
style={{ width: '100%' }}
placeholder="300"
addonAfter={t('pages.xray.seconds')}
onChange={(v) => setLevel0('connIdle', v as number | null)}
/>
}
/>
<SettingListItem
title={t('pages.xray.bufferSize')}
description={t('pages.xray.bufferSizeDesc')}
paddings="small"
control={
<InputNumber
value={typeof level0.bufferSize === 'number' ? level0.bufferSize : undefined}
min={0}
style={{ width: '100%' }}
placeholder={t('pages.xray.bufferSizePlaceholder')}
addonAfter="KB"
onChange={(v) => setLevel0('bufferSize', v as number | null)}
/>
}
/>
</>
),
},
{
key: '3',
label: catTabLabel(<FileTextOutlined />, t('pages.xray.logConfigs'), isMobile),

View File

@@ -28,6 +28,7 @@ export const XraySettingsValueSchema = z.object({
log: z.record(z.string(), z.unknown()).optional(),
policy: z.object({
system: z.record(z.string(), z.boolean()).optional(),
levels: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),
}).loose().optional(),
observatory: z.unknown().optional(),
burstObservatory: z.unknown().optional(),

View File

@@ -1201,6 +1201,14 @@
"statsOutboundUplinkDesc": "Enables the statistics collection for upstream traffic of all outbound proxies.",
"statsOutboundDownlink": "Outbound Download Statistics",
"statsOutboundDownlinkDesc": "Enables the statistics collection for downstream traffic of all outbound proxies.",
"connectionLimits": "Connection Limits",
"connectionLimitsDesc": "Connection-level policies for user level 0. Leave a field empty to use Xray's default.",
"connIdle": "Idle Timeout",
"connIdleDesc": "Closes a connection after it stays idle for this many seconds. Lowering it frees memory and file descriptors faster on busy servers (Xray default: 300).",
"bufferSize": "Buffer Size",
"bufferSizeDesc": "Per-connection internal buffer size in KB. Set to 0 to minimize memory usage on low-RAM servers (Xray default depends on the platform).",
"bufferSizePlaceholder": "auto",
"seconds": "seconds",
"rules": {
"first": "First",
"last": "Last",

View File

@@ -1201,6 +1201,14 @@
"statsOutboundUplinkDesc": "جمع‌آوری آمار برای ترافیک بالارو (آپلود) تمام پروکسی‌های خروجی را فعال می‌کند.",
"statsOutboundDownlink": "آمار دانلود خروجی",
"statsOutboundDownlinkDesc": "جمع‌آوری آمار برای ترافیک پایین‌رو (دانلود) تمام پروکسی‌های خروجی را فعال می‌کند.",
"connectionLimits": "محدودیت اتصال",
"connectionLimitsDesc": "سیاست‌های سطح اتصال برای کاربرانِ سطح ۰. هر فیلد را خالی بگذارید تا مقدار پیش‌فرض Xray استفاده شود.",
"connIdle": "مهلت بی‌کاری",
"connIdleDesc": "اتصال را پس از این تعداد ثانیه بی‌کار ماندن می‌بندد. کم‌کردن آن، روی سرورهای شلوغ حافظه و file descriptor را زودتر آزاد می‌کند (پیش‌فرض Xray: ۳۰۰).",
"bufferSize": "اندازهٔ بافر",
"bufferSizeDesc": "اندازهٔ بافر داخلی هر اتصال بر حسب کیلوبایت. برای کم‌کردن مصرف حافظه روی سرورهای کم‌رم روی ۰ بگذارید (پیش‌فرض Xray به پلتفرم بستگی دارد).",
"bufferSizePlaceholder": "خودکار",
"seconds": "ثانیه",
"rules": {
"first": "اولین",
"last": "آخرین",