feat(misc-viewer): optional delay check interval

This commit is contained in:
Slinetrac
2026-01-23 16:02:58 +08:00
parent d81aa5f233
commit 2608e79d93
19 changed files with 75 additions and 3 deletions

View File

@@ -155,6 +155,9 @@ pub struct IVerge {
/// 是否自动检测当前节点延迟 /// 是否自动检测当前节点延迟
pub enable_auto_delay_detection: Option<bool>, pub enable_auto_delay_detection: Option<bool>,
/// 自动检测当前节点延迟的间隔(分钟)
pub auto_delay_detection_interval_minutes: Option<u64>,
/// 是否使用内部的脚本支持,默认为真 /// 是否使用内部的脚本支持,默认为真
pub enable_builtin_enhanced: Option<bool>, pub enable_builtin_enhanced: Option<bool>,
@@ -523,6 +526,7 @@ impl IVerge {
patch!(default_latency_test); patch!(default_latency_test);
patch!(default_latency_timeout); patch!(default_latency_timeout);
patch!(enable_auto_delay_detection); patch!(enable_auto_delay_detection);
patch!(auto_delay_detection_interval_minutes);
patch!(enable_builtin_enhanced); patch!(enable_builtin_enhanced);
patch!(proxy_layout_column); patch!(proxy_layout_column);
patch!(test_list); patch!(test_list);

View File

@@ -47,7 +47,7 @@ const STORAGE_KEY_PROXY = "clash-verge-selected-proxy";
const STORAGE_KEY_SORT_TYPE = "clash-verge-proxy-sort-type"; const STORAGE_KEY_SORT_TYPE = "clash-verge-proxy-sort-type";
const AUTO_CHECK_INITIAL_DELAY_MS = 1500; const AUTO_CHECK_INITIAL_DELAY_MS = 1500;
const AUTO_CHECK_INTERVAL_MS = 5 * 60 * 1000; const AUTO_CHECK_DEFAULT_INTERVAL_MINUTES = 5;
// 代理节点信息接口 // 代理节点信息接口
interface ProxyOption { interface ProxyOption {
@@ -106,6 +106,14 @@ export const CurrentProxyCard = () => {
const { current: currentProfile } = useProfiles(); const { current: currentProfile } = useProfiles();
const autoDelayEnabled = verge?.enable_auto_delay_detection ?? false; const autoDelayEnabled = verge?.enable_auto_delay_detection ?? false;
const defaultLatencyTimeout = verge?.default_latency_timeout; const defaultLatencyTimeout = verge?.default_latency_timeout;
const autoDelayIntervalMs = useMemo(() => {
const rawInterval = verge?.auto_delay_detection_interval_minutes;
const intervalMinutes =
typeof rawInterval === "number" && rawInterval > 0
? rawInterval
: AUTO_CHECK_DEFAULT_INTERVAL_MINUTES;
return Math.max(1, Math.round(intervalMinutes)) * 60 * 1000;
}, [verge?.auto_delay_detection_interval_minutes]);
const currentProfileId = currentProfile?.uid || null; const currentProfileId = currentProfile?.uid || null;
const getProfileStorageKey = useCallback( const getProfileStorageKey = useCallback(
@@ -592,13 +600,13 @@ export const CurrentProxyCard = () => {
if (disposed) return; if (disposed) return;
await checkCurrentProxyDelay(); await checkCurrentProxyDelay();
if (disposed) return; if (disposed) return;
intervalTimer = setTimeout(runAndSchedule, AUTO_CHECK_INTERVAL_MS); intervalTimer = setTimeout(runAndSchedule, autoDelayIntervalMs);
}; };
initialTimer = setTimeout(async () => { initialTimer = setTimeout(async () => {
await checkCurrentProxyDelay(); await checkCurrentProxyDelay();
if (disposed) return; if (disposed) return;
intervalTimer = setTimeout(runAndSchedule, AUTO_CHECK_INTERVAL_MS); intervalTimer = setTimeout(runAndSchedule, autoDelayIntervalMs);
}, AUTO_CHECK_INITIAL_DELAY_MS); }, AUTO_CHECK_INITIAL_DELAY_MS);
return () => { return () => {
@@ -608,6 +616,7 @@ export const CurrentProxyCard = () => {
}; };
}, [ }, [
checkCurrentProxyDelay, checkCurrentProxyDelay,
autoDelayIntervalMs,
isDirectMode, isDirectMode,
state.selection.group, state.selection.group,
state.selection.proxy, state.selection.proxy,

View File

@@ -29,6 +29,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
enableBuiltinEnhanced: true, enableBuiltinEnhanced: true,
proxyLayoutColumn: 6, proxyLayoutColumn: 6,
enableAutoDelayDetection: false, enableAutoDelayDetection: false,
autoDelayDetectionIntervalMinutes: 5,
defaultLatencyTest: "", defaultLatencyTest: "",
autoLogClean: 2, autoLogClean: 2,
defaultLatencyTimeout: 10000, defaultLatencyTimeout: 10000,
@@ -46,6 +47,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true, enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
proxyLayoutColumn: verge?.proxy_layout_column || 6, proxyLayoutColumn: verge?.proxy_layout_column || 6,
enableAutoDelayDetection: verge?.enable_auto_delay_detection ?? false, enableAutoDelayDetection: verge?.enable_auto_delay_detection ?? false,
autoDelayDetectionIntervalMinutes:
verge?.auto_delay_detection_interval_minutes ?? 5,
defaultLatencyTest: verge?.default_latency_test || "", defaultLatencyTest: verge?.default_latency_test || "",
autoLogClean: verge?.auto_log_clean || 0, autoLogClean: verge?.auto_log_clean || 0,
defaultLatencyTimeout: verge?.default_latency_timeout || 10000, defaultLatencyTimeout: verge?.default_latency_timeout || 10000,
@@ -65,6 +68,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
enable_builtin_enhanced: values.enableBuiltinEnhanced, enable_builtin_enhanced: values.enableBuiltinEnhanced,
proxy_layout_column: values.proxyLayoutColumn, proxy_layout_column: values.proxyLayoutColumn,
enable_auto_delay_detection: values.enableAutoDelayDetection, enable_auto_delay_detection: values.enableAutoDelayDetection,
auto_delay_detection_interval_minutes:
values.autoDelayDetectionIntervalMinutes,
default_latency_test: values.defaultLatencyTest, default_latency_test: values.defaultLatencyTest,
default_latency_timeout: values.defaultLatencyTimeout, default_latency_timeout: values.defaultLatencyTimeout,
auto_log_clean: values.autoLogClean as any, auto_log_clean: values.autoLogClean as any,
@@ -323,6 +328,44 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
/> />
</ListItem> </ListItem>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText
primary={t(
"settings.modals.misc.fields.autoDelayDetectionInterval",
)}
sx={{ maxWidth: "fit-content" }}
/>
<TextField
autoComplete="new-password"
size="small"
type="number"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
sx={{ width: 160, marginLeft: "auto" }}
value={values.autoDelayDetectionIntervalMinutes}
disabled={!values.enableAutoDelayDetection}
onChange={(e) => {
const parsed = parseInt(e.target.value, 10);
const intervalMinutes =
Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
setValues((v) => ({
...v,
autoDelayDetectionIntervalMinutes: intervalMinutes,
}));
}}
slotProps={{
input: {
endAdornment: (
<InputAdornment position="end">
{t("shared.units.minutes")}
</InputAdornment>
),
},
}}
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}> <ListItem sx={{ padding: "5px 2px" }}>
<ListItemText <ListItemText
primary={t("settings.modals.misc.fields.defaultLatencyTest")} primary={t("settings.modals.misc.fields.defaultLatencyTest")}

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "أعمدة عرض الوكيل", "proxyLayoutColumns": "أعمدة عرض الوكيل",
"autoLogClean": "تنظيف السجلات تلقائيًا", "autoLogClean": "تنظيف السجلات تلقائيًا",
"autoDelayDetection": "اكتشاف التأخير التلقائي", "autoDelayDetection": "اكتشاف التأخير التلقائي",
"autoDelayDetectionInterval": "الفاصل الزمني لاكتشاف التأخير التلقائي",
"defaultLatencyTest": "اختبار التأخير الافتراضي", "defaultLatencyTest": "اختبار التأخير الافتراضي",
"defaultLatencyTimeout": "مهلة التأخير الافتراضية" "defaultLatencyTimeout": "مهلة التأخير الافتراضية"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Anzahl der Spalten im Proxy-Layout", "proxyLayoutColumns": "Anzahl der Spalten im Proxy-Layout",
"autoLogClean": "Protokolle automatisch bereinigen", "autoLogClean": "Protokolle automatisch bereinigen",
"autoDelayDetection": "Automatische Latenzprüfung", "autoDelayDetection": "Automatische Latenzprüfung",
"autoDelayDetectionInterval": "Intervall für automatische Latenzprüfung",
"defaultLatencyTest": "Standard-Testlink", "defaultLatencyTest": "Standard-Testlink",
"defaultLatencyTimeout": "Test-Timeout" "defaultLatencyTimeout": "Test-Timeout"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Proxy Layout Columns", "proxyLayoutColumns": "Proxy Layout Columns",
"autoLogClean": "Auto Log Clean", "autoLogClean": "Auto Log Clean",
"autoDelayDetection": "Auto Delay Detection", "autoDelayDetection": "Auto Delay Detection",
"autoDelayDetectionInterval": "Auto Delay Detection Interval",
"defaultLatencyTest": "Default Latency Test", "defaultLatencyTest": "Default Latency Test",
"defaultLatencyTimeout": "Default Latency Timeout" "defaultLatencyTimeout": "Default Latency Timeout"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Número de columnas en la disposición de la página de proxy", "proxyLayoutColumns": "Número de columnas en la disposición de la página de proxy",
"autoLogClean": "Limpiar registros automáticamente", "autoLogClean": "Limpiar registros automáticamente",
"autoDelayDetection": "Detección automática de latencia", "autoDelayDetection": "Detección automática de latencia",
"autoDelayDetectionInterval": "Intervalo de detección automática de latencia",
"defaultLatencyTest": "Enlace de prueba de latencia predeterminado", "defaultLatencyTest": "Enlace de prueba de latencia predeterminado",
"defaultLatencyTimeout": "Tiempo de espera de la prueba de latencia" "defaultLatencyTimeout": "Tiempo de espera de la prueba de latencia"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "ستون چیدمان پراکسی", "proxyLayoutColumns": "ستون چیدمان پراکسی",
"autoLogClean": "پاکسازی خودکار لاگ", "autoLogClean": "پاکسازی خودکار لاگ",
"autoDelayDetection": "تشخیص تأخیر خودکار", "autoDelayDetection": "تشخیص تأخیر خودکار",
"autoDelayDetectionInterval": "فاصله تشخیص تأخیر خودکار",
"defaultLatencyTest": "آزمون تأخیر پیش‌فرض", "defaultLatencyTest": "آزمون تأخیر پیش‌فرض",
"defaultLatencyTimeout": "زمان انتظار تأخیر پیش‌فرض" "defaultLatencyTimeout": "زمان انتظار تأخیر پیش‌فرض"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Kolom Tata Letak Proksi", "proxyLayoutColumns": "Kolom Tata Letak Proksi",
"autoLogClean": "Pembersihan Log Otomatis", "autoLogClean": "Pembersihan Log Otomatis",
"autoDelayDetection": "Deteksi Latensi Otomatis", "autoDelayDetection": "Deteksi Latensi Otomatis",
"autoDelayDetectionInterval": "Interval Deteksi Latensi Otomatis",
"defaultLatencyTest": "Tes Latensi Default", "defaultLatencyTest": "Tes Latensi Default",
"defaultLatencyTimeout": "Waktu Habis Latensi Default" "defaultLatencyTimeout": "Waktu Habis Latensi Default"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "プロキシページのレイアウト列数", "proxyLayoutColumns": "プロキシページのレイアウト列数",
"autoLogClean": "ログを自動的にクリーンアップ", "autoLogClean": "ログを自動的にクリーンアップ",
"autoDelayDetection": "自動遅延検出", "autoDelayDetection": "自動遅延検出",
"autoDelayDetectionInterval": "自動遅延検出間隔",
"defaultLatencyTest": "デフォルトの遅延テストURL", "defaultLatencyTest": "デフォルトの遅延テストURL",
"defaultLatencyTimeout": "テストタイムアウト時間" "defaultLatencyTimeout": "テストタイムアウト時間"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "프록시 레이아웃 열 수", "proxyLayoutColumns": "프록시 레이아웃 열 수",
"autoLogClean": "로그 자동 정리", "autoLogClean": "로그 자동 정리",
"autoDelayDetection": "자동 지연 감지", "autoDelayDetection": "자동 지연 감지",
"autoDelayDetectionInterval": "자동 지연 감지 간격",
"defaultLatencyTest": "기본 지연 테스트", "defaultLatencyTest": "기본 지연 테스트",
"defaultLatencyTimeout": "기본 지연 제한시간" "defaultLatencyTimeout": "기본 지연 제한시간"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Количество столбцов в макете прокси", "proxyLayoutColumns": "Количество столбцов в макете прокси",
"autoLogClean": "Автоматическая очистка логов", "autoLogClean": "Автоматическая очистка логов",
"autoDelayDetection": "Автоматическое измерение задержки", "autoDelayDetection": "Автоматическое измерение задержки",
"autoDelayDetectionInterval": "Интервал автоматического измерения задержки",
"defaultLatencyTest": "Ссылка на тест задержки", "defaultLatencyTest": "Ссылка на тест задержки",
"defaultLatencyTimeout": "Таймаут задержки по умолчанию" "defaultLatencyTimeout": "Таймаут задержки по умолчанию"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Vekil Düzeni Sütunları", "proxyLayoutColumns": "Vekil Düzeni Sütunları",
"autoLogClean": "Otomatik Günlük Temizleme", "autoLogClean": "Otomatik Günlük Temizleme",
"autoDelayDetection": "Otomatik Gecikme Tespiti", "autoDelayDetection": "Otomatik Gecikme Tespiti",
"autoDelayDetectionInterval": "Otomatik Gecikme Tespiti Aralığı",
"defaultLatencyTest": "Varsayılan Gecikme Testi", "defaultLatencyTest": "Varsayılan Gecikme Testi",
"defaultLatencyTimeout": "Varsayılan Gecikme Zaman Aşımı" "defaultLatencyTimeout": "Varsayılan Gecikme Zaman Aşımı"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "Прокси күрсәтү баганалары саны", "proxyLayoutColumns": "Прокси күрсәтү баганалары саны",
"autoLogClean": "Логларны автоматик чистарту", "autoLogClean": "Логларны автоматик чистарту",
"autoDelayDetection": "Автоматик тоткарлык ачыклау", "autoDelayDetection": "Автоматик тоткарлык ачыклау",
"autoDelayDetectionInterval": "Автоматик тоткарлык ачыклау интервалы",
"defaultLatencyTest": "Тоткарлануны тикшерү сылтамасы (defaults)", "defaultLatencyTest": "Тоткарлануны тикшерү сылтамасы (defaults)",
"defaultLatencyTimeout": "Тоткарлануның стандарт таймауты" "defaultLatencyTimeout": "Тоткарлануның стандарт таймауты"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "代理页布局列数", "proxyLayoutColumns": "代理页布局列数",
"autoLogClean": "自动清理日志", "autoLogClean": "自动清理日志",
"autoDelayDetection": "自动延迟检测", "autoDelayDetection": "自动延迟检测",
"autoDelayDetectionInterval": "自动延迟检测间隔",
"defaultLatencyTest": "默认测试链接", "defaultLatencyTest": "默认测试链接",
"defaultLatencyTimeout": "测试超时时间" "defaultLatencyTimeout": "测试超时时间"
}, },

View File

@@ -377,6 +377,7 @@
"proxyLayoutColumns": "代理頁面欄數", "proxyLayoutColumns": "代理頁面欄數",
"autoLogClean": "自動清理日誌", "autoLogClean": "自動清理日誌",
"autoDelayDetection": "自動延遲偵測", "autoDelayDetection": "自動延遲偵測",
"autoDelayDetectionInterval": "自動延遲偵測間隔",
"defaultLatencyTest": "預設測試網址", "defaultLatencyTest": "預設測試網址",
"defaultLatencyTimeout": "測試逾時" "defaultLatencyTimeout": "測試逾時"
}, },

View File

@@ -535,6 +535,7 @@ export const translationKeys = [
"settings.modals.misc.fields.proxyLayoutColumns", "settings.modals.misc.fields.proxyLayoutColumns",
"settings.modals.misc.fields.autoLogClean", "settings.modals.misc.fields.autoLogClean",
"settings.modals.misc.fields.autoDelayDetection", "settings.modals.misc.fields.autoDelayDetection",
"settings.modals.misc.fields.autoDelayDetectionInterval",
"settings.modals.misc.fields.defaultLatencyTest", "settings.modals.misc.fields.defaultLatencyTest",
"settings.modals.misc.fields.defaultLatencyTimeout", "settings.modals.misc.fields.defaultLatencyTimeout",
"settings.modals.misc.tooltips.autoCloseConnections", "settings.modals.misc.tooltips.autoCloseConnections",

View File

@@ -941,6 +941,7 @@ export interface TranslationResources {
autoCheckUpdate: string; autoCheckUpdate: string;
autoCloseConnections: string; autoCloseConnections: string;
autoDelayDetection: string; autoDelayDetection: string;
autoDelayDetectionInterval: string;
autoLogClean: string; autoLogClean: string;
defaultLatencyTest: string; defaultLatencyTest: string;
defaultLatencyTimeout: string; defaultLatencyTimeout: string;

View File

@@ -946,6 +946,7 @@ interface IVergeConfig {
default_latency_test?: string; default_latency_test?: string;
default_latency_timeout?: number; default_latency_timeout?: number;
enable_auto_delay_detection?: boolean; enable_auto_delay_detection?: boolean;
auto_delay_detection_interval_minutes?: number;
enable_builtin_enhanced?: boolean; enable_builtin_enhanced?: boolean;
auto_log_clean?: 0 | 1 | 2 | 3 | 4; auto_log_clean?: 0 | 1 | 2 | 3 | 4;
enable_auto_backup_schedule?: boolean; enable_auto_backup_schedule?: boolean;