fix(routing): scope excluded_ips to section rules, humanize section names, and add component visibility

This commit is contained in:
Dushnilin
2026-09-16 16:16:32 +03:00
parent 94d629b8bb
commit 0f5967e51c
24 changed files with 6356 additions and 5503 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+41 -2
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: TACHYON\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-16 15:18+0300\n"
"PO-Revision-Date: 2026-09-16 15:18+0300\n"
"POT-Creation-Date: 2026-09-16 16:15+0300\n"
"PO-Revision-Date: 2026-09-16 16:15+0300\n"
"Last-Translator: Dushnilin\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -311,6 +311,9 @@ msgstr "Chat ID администраторов"
msgid "Adult content"
msgstr "Взрослый контент"
msgid "Advanced DPI bypass engine with Lua scripts (nfqws2)"
msgstr ""
msgid "Advanced System"
msgstr "Расширенные настройки"
@@ -1079,6 +1082,9 @@ msgstr "Community-списки"
msgid "Component action timed out"
msgstr "Превышено время ожидания действия компонента"
msgid "Component Cards Visibility"
msgstr ""
msgid "Component update available"
msgstr "Доступно обновление компонента"
@@ -1184,6 +1190,9 @@ msgstr "Скопировать отчет для поддержки"
msgid "Core configuration and preferences"
msgstr "Основные настройки и параметры"
msgid "Core orchestration service and LuCI application"
msgstr ""
msgid "Could not compare FakeIP and control public IPs"
msgstr "Не удалось сравнить публичные IP FakeIP и контрольной проверки"
@@ -1253,6 +1262,9 @@ msgstr "Пользовательская стратегия добавлена!"
msgid "Customize the order and visibility of tabs in the main navigation menu. Use the arrows to reorder and checkboxes to show or hide tabs."
msgstr "Настройте порядок и видимость вкладок в главном меню навигации. Используйте стрелки для перемещения и галочки для показа или скрытия."
msgid "Customize which component cards are displayed in the Components tab. Checkboxes show or hide components."
msgstr ""
msgid "Daily Quota"
msgstr "Дневная квота"
@@ -1286,6 +1298,9 @@ msgstr "Дни недели"
msgid "Dedicated cgroup unavailable"
msgstr "Выделенная cgroup недоступна"
msgid "Dedicated direct HTTP/SOCKS5 outbound proxy"
msgstr ""
msgid "Default"
msgstr "По умолчанию"
@@ -1370,6 +1385,9 @@ msgstr "Прямое (по умолчанию)"
msgid "Direct Bypass"
msgstr "Прямой WAN"
msgid "Direct cgroup bypass for TorrServer"
msgstr ""
msgid "Direct connection"
msgstr "Прямое подключение"
@@ -1622,6 +1640,9 @@ msgstr "Загрузка и применение наборов правил и
msgid "DPI bandwidth throttling or delay detected — connection throttled during data transfer."
msgstr "Обнаружено замедление DPI — соединение заблокировано или задушено при передаче данных."
msgid "DPI bypass engine (nfqws v1)"
msgstr ""
msgid "DPI Detected"
msgstr "DPI обнаружен"
@@ -2126,6 +2147,9 @@ msgstr "Семейные профили"
msgid "Family profiles and device grouping"
msgstr "Семейные профили и группировка устройств"
msgid "Fast packet transport network client"
msgstr ""
msgid "Faster DNS health monitoring than the default cycle. Switches bootstrap DNS on failure."
msgstr "Более быстрый мониторинг состояния DNS, чем стандартный цикл. Переключает bootstrap DNS при сбое."
@@ -3071,6 +3095,9 @@ msgstr "Загрузка..."
msgid "Local Address"
msgstr "Локальный адрес"
msgid "Local SOCKS proxy desynchronizer (ciadpi)"
msgstr ""
msgid "Location"
msgstr "Местоположение"
@@ -3959,6 +3986,9 @@ msgstr "Ошибка чтения"
msgid "Ready to benchmark DNS providers"
msgstr "Готов к тестированию DNS провайдеров"
msgid "Real-time WebRTC anti-censorship tunnel"
msgstr ""
msgid "Reality fake site"
msgstr "Фейковый сайт Reality"
@@ -5489,6 +5519,9 @@ msgstr "Великобритания (gb)"
msgid "United States (us)"
msgstr "США (us)"
msgid "Universal proxy platform routing engine"
msgstr ""
msgid "unknown"
msgstr "неизвестно"
@@ -5834,6 +5867,9 @@ msgstr "Будни (Пн-Пт)"
msgid "Weekends (Sat-Sun)"
msgstr "Выходные (Сб-Вс)"
msgid "Western Digital Tunnel Transport"
msgstr ""
msgid "What Tachyon should do when this section matches"
msgstr "Что должен делать Tachyon при совпадении этой секции"
@@ -5942,6 +5978,9 @@ msgstr "Правила маршрутизации sing-box для Zapret2 нас
msgid "Zapret2 sing-box route rules are not configured"
msgstr "Правила маршрутизации sing-box для Zapret2 не настроены"
msgid "Zero config mesh VPN daemon"
msgstr ""
msgid "Testing strategy"
msgstr "Тестирование стратегии"
@@ -137,7 +137,7 @@ export function resetDirectClashApiState() {
}
function getDisplayName(section: Tachyon.ConfigSection) {
return section.label || section['.name'];
return section.label || (section as any).name || section['.name'];
}
function getSettingsSection(configSections: Tachyon.ConfigSection[]) {
@@ -1806,6 +1806,7 @@ export async function getDashboardSections(
code: outbound?.code || sectionName,
displayName:
section.label ||
(section as any).name ||
section.interface ||
customName ||
defaultLabel,
@@ -1589,11 +1589,17 @@ function handleOpenLeakCheck() {
function handleOpenStrategyFuzzer() {
getConfigSections()
.then((sections) => {
const ruleNames = sections
const ruleSections = sections
.filter((s) => s['.type'] === 'section' || s['.type'] === 'rule')
.map((s) => s.name || s['.name'])
.filter((n): n is string => Boolean(n));
renderStrategyFuzzerModal(ruleNames);
.map((s) => ({
id: s['.name'],
label:
(typeof s.label === 'string' && s.label.trim()) ||
(typeof s.name === 'string' && s.name.trim()) ||
s['.name'],
}))
.filter((r) => Boolean(r.id));
renderStrategyFuzzerModal(ruleSections);
})
.catch(() => {
renderStrategyFuzzerModal([]);
@@ -3,7 +3,17 @@ import { renderButton } from '../../../../partials';
import { showToast } from '../../../../helpers/showToast';
import { Tachyon } from '../../../types';
export function renderStrategyFuzzerModal(ruleNames: string[] = []) {
export interface FuzzerRuleSection {
id: string;
label: string;
}
export function renderStrategyFuzzerModal(
ruleNames: Array<string | FuzzerRuleSection> = [],
) {
const normalizedRules: FuzzerRuleSection[] = ruleNames.map((r) =>
typeof r === 'string' ? { id: r, label: r } : r,
);
let pollingInterval: ReturnType<typeof setInterval> | null = null;
let isPolling = false;
@@ -292,7 +302,9 @@ export function renderStrategyFuzzerModal(ruleNames: string[] = []) {
{ class: 'cbi-input-select', style: 'width: 100%;' },
[
E('option', { value: '', selected: true }, _('Provider Global Default')),
...ruleNames.map((r) => E('option', { value: r }, `${_('Rule:')} ${r}`)),
...normalizedRules.map((r) =>
E('option', { value: r.id }, `${_('Rule:')} ${r.label}`),
),
],
);
ruleSelect.addEventListener('change', () => {
@@ -2035,19 +2047,23 @@ export function renderStrategyFuzzerModal(ruleNames: string[] = []) {
selectedRuleSection,
);
if (res.success) {
const targetLabel =
normalizedRules.find((r) => r.id === selectedRuleSection)?.label ||
selectedRuleSection ||
_('Global Default');
if (typeof ui?.addNotification === 'function') {
ui.addNotification(
_('Tachyon'),
E(
'p',
{},
`${_('Strategy applied successfully and service reloaded!')} (${item.name} -> ${selectedRuleSection || _('Global Default')})`,
`${_('Strategy applied successfully and service reloaded!')} (${item.name} -> ${targetLabel})`,
),
'info',
);
} else {
showToast(
`${_('Applied')} "${item.name}" -> ${selectedRuleSection || _('Global Default')}`,
`${_('Applied')} "${item.name}" -> ${targetLabel}`,
'success',
);
}
@@ -169,4 +169,17 @@ describe('renderStrategyFuzzerModal', () => {
await new Promise((resolve) => setTimeout(resolve, 20));
expect(TachyonShellMethods.getFuzzerStatus).toHaveBeenCalled();
});
it('renders rule options with human-readable labels and UCI section IDs', () => {
renderStrategyFuzzerModal([
{ id: 'direct', label: 'Провайдер Direct' },
{ id: 'jobvpn', label: 'Работа VPN' },
]);
expect(mocks.showModal).toHaveBeenCalledTimes(1);
expect(mocks.showModal).toHaveBeenCalledWith(
'⚡ Strategy Fuzzer & Auto-Tuner',
expect.anything(),
);
});
});
@@ -182,7 +182,11 @@ function formatEndpoint(address?: string, port?: string | number): string {
}
function getDisplayName(section: Tachyon.ConfigSection) {
return normalizeString(section.label) || section['.name'];
return (
normalizeString(section.label) ||
normalizeString((section as any).name) ||
section['.name']
);
}
function buildRouteDisplayNames(sections: Tachyon.ConfigSection[]) {
@@ -2029,6 +2029,33 @@ function renderComponentCard(card: ComponentCard) {
return E('div', { class: 'tachyon_updates-page__component' }, cardChildren);
}
function isComponentCardVisible(
card: ComponentCard,
systemInfo: any,
): boolean {
const component = card.component;
if (component === 'tachyon' || component === 'sing_box') {
return true;
}
if (component === 'fptn') {
const fptnInstalled = Boolean(systemInfo.fptn_installed);
const fptnSupported =
systemInfo.fptn_supported === undefined
? true
: Boolean(systemInfo.fptn_supported);
if (!fptnInstalled && !fptnSupported) {
return false;
}
}
const optKey = `show_component_${component}`;
const val = (systemInfo as Record<string, any>)[optKey];
if (val === undefined || val === null || val === '') {
return true;
}
return String(val) === '1' || val === 1;
}
function renderUpdatesComponents() {
const container = document.getElementById('tachyon_updates-components');
@@ -2036,9 +2063,24 @@ function renderUpdatesComponents() {
return;
}
const systemInfo = normalizeSingBoxVariantFields(
store.get().diagnosticsSystemInfo,
);
const visibleCards = getComponentCards().filter((card) =>
isComponentCardVisible(card, systemInfo),
);
const columns: Node[][] = [[], [], []];
getComponentCards().forEach((card) => {
columns[card.column]?.push(renderComponentCard(card));
const colCounts = [0, 0, 0];
visibleCards.forEach((card) => {
colCounts[card.column] = (colCounts[card.column] || 0) + 1;
});
const hasEmptyColumn =
colCounts.some((c) => c === 0) && visibleCards.length >= 3;
visibleCards.forEach((card, idx) => {
const colIdx = hasEmptyColumn ? idx % 3 : card.column;
columns[colIdx]?.push(renderComponentCard(card));
});
return preserveScrollForPage(() => {
+10
View File
@@ -661,6 +661,7 @@ export namespace Tachyon {
tailscale_installed: 0 | 1;
fptn_version: string;
fptn_installed: 0 | 1;
fptn_supported?: 0 | 1;
fptn_backup_version?: string;
fptn_backup_time?: number;
direct_bypass_enabled?: 0 | 1;
@@ -670,6 +671,15 @@ export namespace Tachyon {
torrserver_direct_available?: 0 | 1;
torrserver_direct_enabled?: 0 | 1;
torrserver_direct_active?: 0 | 1;
show_component_zapret?: 0 | 1;
show_component_zapret2?: 0 | 1;
show_component_byedpi?: 0 | 1;
show_component_wdtt?: 0 | 1;
show_component_olcrtc?: 0 | 1;
show_component_fptn?: 0 | 1;
show_component_tailscale?: 0 | 1;
show_component_direct_bypass?: 0 | 1;
show_component_torrserver_direct?: 0 | 1;
openwrt_version: string;
device_model: string;
generated_at?: number;