Refactor VPN proxy routing logic

This commit is contained in:
2026-07-08 09:39:24 +03:00
parent 288acbf0c8
commit 149bb999dc
28 changed files with 2260 additions and 278 deletions

View File

@@ -0,0 +1,188 @@
# UX/UI-аудит Windows-клиента
Дата: 2026-07-08
## Область аудита
Проверен текущий React UI `apps/windows-client` для Vite/Tauri как компактная Windows-утилита управления proxy-маршрутизацией приложений. Аудит выполнялся в browser-preview на `http://127.0.0.1:5174/`, поэтому нативные Tauri-команды были недоступны, а интерфейс показывал preview/runtime-ошибки. Все выводы ниже привязаны к скриншотам, снятым в этом прогоне.
## Цель пользователя
Главная задача пользователя - быстро управлять службами и понять:
- какие компоненты установлены;
- какие службы запущены, остановлены или отсутствуют;
- какое действие доступно прямо сейчас: установить, удалить, запустить, остановить, обновить, добавить или применить;
- что сейчас маршрутизируется;
- через какую цепочку компонентов идет трафик;
- готовы ли ProxiFyre и опциональный Local sing-box;
- можно ли безопасно применить изменения;
- что делать дальше, если что-то сломано.
Цель по доступности: интерфейс должен быть управляемым с клавиатуры, с понятными статусами, читаемым восстановлением после ошибок, предсказуемыми focus states и устойчивой адаптацией к узким размерам Windows-окна.
## Доказательства
1. `01-summary-desktop.png` - панель "Сводка", desktop-ширина. Состояние: смешанное. Главный статус виден, но примененное состояние еще "загружается", а рядом уже показан бейдж "Совпадает".
2. `02-proxifyre-desktop.png` - панель ProxiFyre, desktop-ширина. Состояние: в целом рабочее. Состав компонента и список приложений компактны, но главное действие apply доступно даже при отсутствующих prerequisites.
3. `03-proxy-desktop.png` - панель "VPN / Прокси", desktop-ширина. Состояние: рабочее. Настройка маршрута понятна, но route path выглядит как вторичный текст, а apply-action выглядит валидным до того, как маршрут может успешно примениться.
4. `04-proxy-validation-desktop.png` - невалидный proxy input. Состояние: хорошая база. Inline-валидация находится рядом с полем и отключает действие проверки.
5. `05-summary-narrow.png` - панель "Сводка", узкая ширина. Состояние: напряженное. Контент перестраивается, но нижний log dock и длинные сообщения обрезают важную информацию.
6. `06-proxifyre-narrow.png` - панель ProxiFyre, узкая ширина. Состояние: напряженное. Контролы складываются неплохо, но setup chips переполняются по горизонтали, а нижний dock конкурирует с основной задачей.
## Доменное направление
Ключевые понятия домена: цепочка маршрута, здоровье компонентов, локальный runtime, внешний endpoint, выбранные приложения, сгенерированный конфиг, граница apply/restart, диагностика.
Цветовой мир: темная Windows-оболочка, терминальный черный, зеленый для driver/service ready, amber для предупреждений, красный для блокеров/firewall, синий для links/actions, slate для config-файлов.
Сигнатурный элемент, который стоит усилить: `Service Control Row` - повторяемая строка компонента, где слева состояние службы, в центре человекочитаемый статус, справа одно главное действие и меню дополнительных действий. Route-chain readout тоже нужен, но как объяснение эффекта этих служб: `Apps -> ProxiFyre -> target -> VPN/server`.
Дефолты, которые стоит отбрасывать:
- generic dashboard cards -> service-control utility;
- большая зеленая apply-кнопка всегда видна -> apply gated by readiness + inline blockers;
- raw logs как главный error surface -> сначала человеческое recovery-сообщение, raw details вторым уровнем.
- разрозненные кнопки и анимации -> shared component base с едиными variants/states/motion tokens.
## Сильные стороны
- Приложение уже ощущается как компактная desktop-утилита, а не как сайт. Фиксированный header, tabs, плотные панели и темная системная палитра подходят задаче.
- Продуктовая модель сильная: ProxiFyre и Local sing-box разделены, sing-box не сделан обязательным.
- Inline-валидация SOCKS5-поля расположена рядом с полем и отключает "Проверить", когда формат неверный.
- Зона добавления приложения использует иконки с доступными labels и tooltip, поэтому плотный workflow остается сканируемым.
- Для основных анимаций есть `prefers-reduced-motion`.
- UI использует настоящие `button` и tab roles, а не click-only divs. Это хорошая база для доступности.
## UX-риски
1. Apply выглядит доступным, когда маршрут еще не actionable.
- Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`.
- ProxiFyre отсутствует и список приложений пуст, но "Обновить конфиг" / "Обновить маршрут" ярко-зеленые. Это провоцирует failed action вместо направленного setup.
2. Главная цепочка маршрута не является визуальным фокусом.
- Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`.
- Самая важная mental model - путь трафика, но сейчас он показан plain text в таблице или вторичном блоке. Пользователь вынужден читать фрагменты статуса вместо того, чтобы сразу увидеть цепочку.
3. В "Сводке" есть противоречивое состояние.
- Доказательство: `01-summary-desktop.png`.
- "Состояние загружается" показано рядом с "Совпадает", а система одновременно говорит "Не настроено". Это может создать ощущение, что действий не требуется.
4. Preview/native command failures слишком сырые.
- Доказательства: все скриншоты.
- Dock показывает `Cannot read properties of undefined (reading 'invoke')`. Для разработчика это полезно, но как первичный пользовательский error surface это шум.
5. Bottom log dock конфликтует с узкой компоновкой.
- Доказательства: `05-summary-narrow.png`, `06-proxifyre-narrow.png`.
- Важные сообщения обрезаются до "Компонен..." и "Cannot read prop..."; dock постоянно занимает вертикальное место в и так коротком окне.
6. ProxiFyre setup chips плохо перестраиваются.
- Доказательство: `06-proxifyre-narrow.png`.
- Горизонтальная chip-лента скрывает третий dependency и ухудшает диагностическую ясность.
7. Терминология немного смешана.
- Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`.
- `config`, `TCP check`, `VPN сервер`, `Local sing-box`, `ProxiFyre` - все эти термины допустимы, но нужен единый принцип: сначала пользовательский русский, технический идентификатор вторым уровнем.
8. Компонентная база пока не выражена как система.
- Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`, `06-proxifyre-narrow.png`.
- Кнопки "Обновить", "Установить", "Открыть", "Проверить", add-icon buttons и service actions выглядят близко, но пока не читаются как строгая система variants. Из-за этого сложно гарантировать одинаковые hover/loading/disabled/focus states и одинаковую motion-модель.
## Риски доступности
- Tablist использует `role="tab"`, но не видно поддержки ожидаемого arrow-key behavior и roving tab index. Пользователю с клавиатурой, вероятно, придется проходить все tabs через Tab вместо Left/Right.
- Focus visibility есть через browser defaults, но визуально она тяжелая и не согласована со стилем приложения. Нужен отдельный `:focus-visible` token для buttons, tabs, inputs и icon controls.
- Status dots сильно полагаются на цвет. Стоит дублировать состояние видимым текстом или `aria-label`/screen-reader text там, где текст рядом не объясняет статус.
- Footer использует `aria-live`, но повторяющиеся raw runtime errors могут быть шумными для assistive tech. Сначала стоит объявлять короткий статус, а подробный error text держать за "Посмотреть".
- На узкой ширине truncation может скрывать actionable-часть сообщений и button labels.
- Скриншоты не доказывают полный keyboard order, screen-reader output или contrast ratios. Для этого нужен интерактивный accessibility pass.
## План улучшений
### P0 - Сделать service-control flow заслуживающим доверия
1. Ввести shared component base:
- `Button` с variants: `primary`, `neutral`, `add`, `danger`, `icon`;
- `Tabs` с единым keyboard behavior и animation contract;
- `ServiceControlRow` для ProxiFyre, Local sing-box и будущих служб;
- `StatusPill`, `Field`, `ActionMenu`, `LogDock`;
- единые states: default, hover, active, focus-visible, disabled, loading.
2. Нормализовать motion tokens:
- button press: 100-140ms;
- tab switch: 180-240ms, только `opacity` + `transform`;
- popover/menu: 150-180ms;
- service operation: видимый loading state, чтобы интерфейс не ощущался зависшим;
- не использовать `transition: all`.
3. Заменить raw preview/native invocation failures на дружелюбное состояние:
- "Desktop-команды недоступны в browser preview. Запусти через Tauri для управления службами."
- Raw error оставить только в деталях лога.
4. Заблокировать primary apply actions до готовности:
- disabled + explanation, когда список приложений пуст;
- disabled + explanation, когда ProxiFyre отсутствует;
- disabled + explanation, когда выбран local route без установленного/запущенного sing-box или выбранного сервера;
- "Открыть конфиг" оставить вторичным действием, не равным apply по весу.
5. Исправить язык summary-state:
- использовать взаимоисключающие состояния: "Проверяю", "Не готово", "Готово к применению", "Применено", "Есть черновик";
- не показывать "Совпадает", пока saved/applied state реально не загружен.
### P1 - Пересобрать главную mental model
6. Вынести route-chain component как объясняющий элемент:
- узел `Apps` с количеством;
- узел `ProxiFyre` со статусом installed/running;
- узел `Target`: external SOCKS5 или Local sing-box;
- узел `Server`, когда активен local sing-box;
- каждый сломанный узел показывает одно следующее действие.
7. Переработать "Сводку" в command center:
- сверху: route-chain и readiness системы;
- посередине: applied vs draft diff, только если есть отличие;
- снизу: максимум два next actions;
- длинные config paths и подробный состав компонентов убрать из первого взгляда.
8. Разделить "настроить маршрут" и "применить маршрут":
- Proxy panel отвечает за endpoint choice и connection check;
- ProxiFyre panel отвечает за app selection и service readiness;
- Summary подтверждает объединенный маршрут и применяет только при готовности.
### P2 - Усилить responsive и component craft
7. Превратить setup chips в wrapping checklist на узких ширинах.
8. Сделать log dock адаптивным:
- desktop: persistent compact dock подходит;
- narrow: collapsed toast/details sheet вместо постоянного full-width footer.
9. Определить design tokens:
- surfaces: canvas, panel, inset, elevated;
- text: primary, secondary, muted, disabled;
- status: ready, warning, blocked, checking;
- focus ring и border intensities.
10. Стандартизировать copy:
- последовательно использовать "конфиг" или "конфигурация";
- заменить "TCP check" на "TCP-проверка";
- `Local sing-box` оставить техническим именем компонента, но в user-facing headings связывать с "локальный прокси".
### P3 - Verification pass
11. Добавить focused interaction QA:
- keyboard tab order;
- arrow-key tab navigation;
- focus return из menus/popovers;
- disabled-action explanations;
- empty, loading, error, missing-component, ready и unapplied-change states.
12. Добавить responsive visual snapshots:
- 1280x720 desktop;
- 800x600 compact desktop;
- 420x720 narrow window;
- длинные proxy/server names и длинные Windows paths.
## Рекомендуемый первый redesign slice
Сначала стоит сделать shared UI foundation: `Button`, `Tabs`, `ServiceControlRow`, `StatusPill`, `Field`, `ActionMenu`, `LogDock` и motion tokens. После этого собрать ProxiFyre и Local sing-box через один `ServiceControlRow`, а route-chain использовать как объясняющий компонент в "Сводке" и "VPN / Прокси". Такой порядок сначала стабилизирует поведение кнопок/табы/анимации, затем улучшит ориентацию и recovery без переписывания всего UI.