33 KiB
План реализации трехпанельного интерфейса Windows Client
Intent: Перестроить текущий монолитный экран Windows-клиента в три переключаемые панели: read-only сводка, настройки ProxiFyre и настройки VPN/прокси.
Current Behavior: Сейчас apps/windows-client/src/app/App.tsx смешивает статус ProxiFyre, выбор маршрута, Local sing-box, список приложений, применение конфига и журнал событий на одном экране. Пользователь сразу видит все управляющие элементы, поэтому главная страница не отделяет состояние системы от действий.
Expected Outcome: Пользователь открывает приложение и сначала видит чистую сводку без редактирования. Управление ProxiFyre, список приложений и диагностика компонента находятся во второй панели. Выбор локального или внешнего прокси, подписка, серверы, ping и генерация VPN/proxy-конфига находятся в третьей панели.
Target-Perspective Output: Пользователь может за 5-10 секунд понять, работает ли система, запущен ли ProxiFyre, какой маршрут применен, локальный он или внешний, и какой файл конфига активен. Затем пользователь переключается во вкладку ProxiFyre для сервисных действий и списка приложений либо во вкладку VPN/Прокси для выбора маршрута и проверки соединения.
Truth Owner: Rust/Tauri команды и JSON-файлы под C:\ProgramData\VpnProxy остаются источником правды. React хранит только состояние текущей вкладки, черновики полей, loading/error/success состояния и производные view model для отображения.
Contract Boundary: UI вызывает существующие typed Tauri commands из apps/windows-client/src/api/tauriCommands.ts. Rust владеет профилями, targets, компонентами, local-singbox config/cache, generated config и применением ProxiFyre. Новые UI-панели не должны писать напрямую в derived/generated артефакты.
Cutover: Текущий единый экран в App.tsx заменяется shell-layout с тремя вкладками. Существующие функции загрузки, установки, запуска, выбора сервера, ping, apply и notifications переиспользуются, но раскладываются по панелям.
Displaced Path: Убирается доминирующий путь "все настройки на одной странице". Сводка не дублирует формы и кнопки apply; она только отображает состояние и ведет пользователя к нужной панели.
Value Density: Самый ценный срез: верхняя навигация по трем панелям плюс read-only сводка, которая корректно собирает текущее состояние из уже загружаемых данных. После этого переносим существующие настройки без изменения backend-контракта.
Evidence Gate: Приемка требует не только npm run build, но и доказательство глазами пользователя: скриншоты/состояния всех трех панелей, read-only поведение сводки, dirty/apply состояние на вкладках настроек, responsive-проверка.
Acceptance Evidence: npm run build проходит; при необходимости Rust tests проходят для нового ping/target DTO; в EVIDENCE.md записаны скриншоты или browser/Tauri state для трех панелей, а также проверка, что сводка не содержит изменяющих controls.
Evidence Lane: Доказательства исполнения будут фиксироваться в docs/goals/windows-client-three-panel-ui/EVIDENCE.md.
Kill Criteria: Нет input/button apply на сводке; нет второго источника состояния маршрута; нет скрытой установки компонентов при открытии вкладок; нет изменения root src/web или root src/server; нет расхождения терминов ProxiFyre / Local sing-box / внешний прокси.
Architecture Slice: Изменения сосредоточены в apps/windows-client/src/app/App.tsx, apps/windows-client/src/styles/app.css, при необходимости apps/windows-client/src/api/tauriCommands.ts, apps/windows-client/src/domain/types.ts, apps/windows-client/src-tauri/src/commands.rs и связанных tests для проверки внешнего target ping.
Plan Review Gate: Требуется PRE review перед исполнением.
Краткий дизайн-brief
Продукт: Windows desktop utility для маршрутизации выбранных приложений через ProxiFyre и внешний или локальный proxy path.
Визуальный источник: текущий темный utilitarian-стиль apps/windows-client/src/styles/app.css: компактные панели, 4px radius, статусные точки, lucide icons, сдержанные borders, без landing/hero.
Интерактивность: полная. Вкладки, меню, установка/запуск/остановка, добавление приложений, выбор маршрута, подписка, выбор сервера, ping, генерация и apply должны работать через реальные текущие команды.
Архитектурный срез
Файлы для создания:
docs/goals/windows-client-three-panel-ui/PLAN.mddocs/goals/windows-client-three-panel-ui/GOAL.mddocs/goals/windows-client-three-panel-ui/EVIDENCE.md
Файлы для изменения:
apps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.cssapps/windows-client/src/api/tauriCommands.ts, только если понадобится новый внешний proxy ping command.apps/windows-client/src/domain/types.ts, только если понадобится новый DTO для внешнего proxy ping.apps/windows-client/src-tauri/src/commands.rs, только если понадобится новый внешний proxy ping command.apps/windows-client/src-tauri/src/main.rs, только для регистрации нового command.apps/windows-client/src-tauri/tests/*, только для нового command или сохранения существующих контрактов.docs/goals/windows-client-three-panel-ui/EVIDENCE.md, при исполнении.
Файлы, которых не касаться:
src/web/*src/server/*- Docker/compose/entrypoint файлы.
- Installer scripts, если UI-разрез не требует изменения install boundary.
- Старые goal packages, кроме ссылок в evidence при необходимости.
Источник правды:
C:\ProgramData\VpnProxy\config\profiles.jsonC:\ProgramData\VpnProxy\config\targets.jsonC:\ProgramData\VpnProxy\config\components.jsonC:\ProgramData\VpnProxy\config\local-singbox.jsonC:\ProgramData\VpnProxy\state\singbox-subscription-cache.jsonC:\ProgramData\VpnProxy\state\activity.json
Производные артефакты:
C:\ProgramData\VpnProxy\generated\proxifyre-app-config.jsonC:\ProgramData\VpnProxy\generated\sing-box-config.json
Путь чтения:
- React вызывает
get_saved_state,get_components,get_proxifyre_setup_status,get_singbox_status,get_singbox_setup_status. - Summary panel строит производную view model из уже загруженных
profiles,targets,components,setupStatus,singBoxStatus,generatedConfigPath,serverPingsиhasUnappliedChanges. - ProxiFyre panel читает
proxyfier,setupStatus,items,loadedProfiles,generatedConfigPath. - VPN/Proxy panel читает
routeMode,proxyInput,singBoxStatus,singBoxSetupStatus,serverPings, selected server и target.
Путь записи:
- ProxiFyre panel пишет только через существующие handlers: install/start/stop/uninstall ProxiFyre, add/remove app items,
updateConfig. - VPN/Proxy panel пишет только через route/subscription/server/config handlers:
changeRouteMode,changeProxyInput,saveSingBoxSubscription,fetchSingBoxSubscription,forgetSingBoxSubscription,selectSingBoxServer,ping*,generateSingBoxConfig, service actions,updateConfig. - Summary panel не пишет ничего, кроме глобального non-mutating refresh, если refresh остается в header.
Граница контракта:
App.tsxотвечает за orchestration и view composition.- Typed Tauri command wrappers отвечают за API shape.
- Rust commands отвечают за validation, persistence, service/check actions и generated config.
- CSS отвечает за layout, tab transitions, loading skeletons, menu/popover transitions и responsive behavior.
Точки интеграции:
routeMode === 'external'показывает внешний/глобальный proxy target.routeMode === 'local-singbox'показывает Local sing-box path.hasUnappliedChangesостается общим индикатором для вкладок настроек.log-dockостается глобальным и не привязывается к одной вкладке.
Миграция и переключение:
- Сначала добавить
activePanelи shell-вкладки без изменения бизнес-логики. - Затем перенести JSX блоки в три render-функции или локальные компоненты в том же файле.
- После стабилизации можно вынести панели в отдельные файлы, но только если это уменьшит размер
App.tsxбез изменения контрактов.
Гейт приемочных доказательств:
- Доказательство должно показать каждую панель отдельно.
- Должно быть видно, что summary read-only.
- Должно быть видно, что actions доступны на вкладках настроек.
- Должно быть видно, что mobile layout не ломает tab bar, app list, server list и bottom log dock.
Детальное описание интерфейса
Общая оболочка
Верхняя часть экрана остается компактной, но становится навигационной:
- слева:
VPN Proxyи заголовокПрокси для приложений; - справа: кнопка
Обновить, которая запускает текущийrefresh; - под заголовком: segmented tabs из трех пунктов:
Сводка,ProxiFyre,VPN / Прокси.
Поведение вкладок:
- активная вкладка имеет более яркий border/background и status underline;
- при клике меняется только
activePanel, данные не перезагружаются автоматически; - переход между панелями: fade + легкий slide по Y на 6-8px, длительность 140-180ms;
- при
prefers-reduced-motion: reducetransition отключается; - keyboard support: tabs работают как buttons с
aria-pressedилиrole="tablist"/role="tab"/role="tabpanel.
Глобальные состояния:
isLoadingпоказывает skeleton в содержимом активной панели;isDetectingComponentsпоказывает проверку компонентов без блокировки переключения вкладок;log-dockостается закрепленным снизу и продолжает показывать success/error/info;- dirty/apply bar появляется только на вкладках
ProxiFyreиVPN / Прокси, не на read-only сводке.
Панель 1: Сводка
Назначение: главная read-only страница, которая отвечает на вопрос "что сейчас происходит с системой".
Содержимое:
Статус системы: одно агрегированное состояниеРаботает,Требует внимания,Не настроено,Проверяю.ProxiFyre: установлен/не установлен, запущен/остановлен, путь или первая проблема.Подключение: корректность текущего маршрута: ProxiFyre running, выбран target, для Local sing-box выбран сервер и служба запущена, для внешнего proxy валиден host/port и есть последний результат ping/check, если он уже запускался.Маршрут:Локальный проксиилиВнешний прокси; рядом человекочитаемый endpoint:127.0.0.1:1080, LAN адрес Local sing-box или внешнийhost:port.Активный сервер: selected Local sing-box server tag, если применим; иначене используется.Приложения в профиле: количество настроенных process/folder/exe items.Примененный конфиг: путьgeneratedConfigPathдля ProxiFyre и, если есть,singBoxStatus.generatedConfigPath.Состояние изменений:Все примененоилиЕсть непримененные изменения, но без кнопки apply.Последнее событие: последний элементlogEntriesили activity, если он уже доступен на клиенте.
Визуально:
- это не форма, а read-only dashboard;
- вместо input используются value rows: label слева, value справа, status dot рядом;
- важные значения не спрятаны в tooltip;
- длинные пути переносятся через
overflow-wrap: anywhere; - при широкой ширине блоки идут сеткой 2-3 колонки, на узком экране складываются в один столбец.
Действия при нажатии:
- клик по строке
ProxiFyreпереключает на вкладкуProxiFyre; - клик по строке
МаршрутилиАктивный серверпереключает на вкладкуVPN / Прокси; - клик по
Приложения в профилепереключает на вкладкуProxiFyreи фокусирует список приложений; - никаких input, add/remove, install/start/stop, apply или clear на этой панели нет.
Анимации:
- при refresh status rows показывают мягкий shimmer/skeleton;
- status dot для
Проверяюиспользует текущий spinner pattern; - при смене агрегированного статуса value row подсвечивается на 400-600ms через background flash;
- предупреждение
Есть непримененные измененияможет слегка проявляться fade-in, но без кнопки.
Панель 2: ProxiFyre
Назначение: диагностика и настройка того, что относится именно к ProxiFyre и маршрутизируемым приложениям.
Содержимое:
- главный статус ProxiFyre: найден/не найден, запущен/остановлен, path/problem;
- setup/modules list из
setupStatus.items: binary/service/install folder/config capability и все, что возвращает backend; - service controls: install, start, stop, uninstall через меню
MoreHorizontal; Список приложений: настроенные process/folder/exe items, сгруппированные или помеченные типом;- счетчик приложений и отдельные пустые состояния для "ничего не настроено";
- generated ProxiFyre config path;
- dirty/apply state для изменений списка приложений.
Визуально:
- верхний status block сохраняет текущий
finder-cardpattern, status-light и animated border glow; - modules list разворачивается внутри панели через
Состав ProxiFyre/Что будет установлено; - список приложений становится основной частью панели, а не хвостом общей страницы;
- app rows имеют icon по типу: process, exe, folder;
- add-toolbar остается с icon buttons: process, exe, folder, с tooltip/title.
Действия при нажатии:
Установить: вызывает текущийinstallProxiFyrePackage, показывает loading на кнопке и animated border;Запустить/Остановить: вызываетsetProxiFyreServiceRunning, блокирует повторный клик на время action;Ещеоткрывает popover сУдалить ProxiFyre; uninstall сохраняет текущий confirm boundary;Состав ProxiFyre: раскрывает/скрывает setup details;Добавить процесс: открывает inline input, Enter добавляет, Escape закрывает;Добавить EXE: открывает file picker через Tauri dialog;Добавить папку: открывает directory picker;Удалитьу app row удаляет item и выставляетhasUnappliedChanges;Применить в ProxiFyre: валидирует items и текущий route, затем вызываетupdateConfig;Открыть конфиг: открывает generated config location, если эта кнопка остается в ProxiFyre panel.
Анимации:
- поиск/установка/запуск используют существующий moving border glow;
- раскрытие modules list: height/opacity transition 160-220ms;
- добавление app row: fade/slide-in;
- удаление app row: быстрый opacity collapse, если реализация не усложнит state;
- dirty bar появляется slide-up/fade-in над command row;
- меню
Еще: fade + scale 0.98 -> 1.
Панель 3: VPN / Прокси
Назначение: выбор маршрута и настройка самого proxy/VPN path.
Содержимое:
- segmented control
Внешний прокси/Локальный прокси; - для
Внешний прокси: input адресаsocks5://host:portилиhost:port, validation hint, кнопка проверки доступности; - для
Локальный прокси: Local sing-box status, install/start/stop/uninstall, setup details, локальный и LAN endpoint, selected server, generated sing-box config path; - subscription input: paste URL/link, load/update, clear;
- server list из
singBoxStatus.cache.servers; - ping controls:
Ping все, per-server ping action, отображение latency/error рядом с server row; - generate sing-box config action;
- route preview:
Выбранные приложения -> ProxiFyre -> внешний proxyилиВыбранные приложения -> ProxiFyre -> Local sing-box -> selected server; - dirty/apply state для route/proxy/subscription/server changes.
Визуально:
- mode switch остается заметным вверху панели;
- внешний proxy block не должен выглядеть менее важным, потому что это полноценный route path;
- Local sing-box block визуально похож на ProxiFyre status block, но расположен только в VPN/Proxy panel;
- server list может оставаться grid, но row должен показывать selected dot, server name и ping badge;
- для плохого ping row получает amber/red border, для хорошего ping зеленый badge;
- route preview оформляется как read-only line/flow, без декоративной схемы.
Действия при нажатии:
Внешний прокси: меняетrouteModeнаexternal, выставляет dirty state;- ввод адреса proxy: обновляет
proxyInput, выставляет dirty state, frontend validation показывает ошибки до apply; Проверить: парсит внешний proxy и вызывает новый или переиспользованный backend TCP connect check; результат сохраняется в UI state и отображается на этой панели и в summary;Локальный прокси: меняетrouteModeнаlocal-singbox, выставляет dirty state;Установить Local sing-box: вызывает текущий install handler;Запустить/Остановить: вызывает текущий service handler;Состав Local sing-box: раскрывает setup details;Подробности: показывает локальный endpoint, LAN, server, binary path, config path;Загрузить/Обновитьподписку: вызывает текущий subscription flow;Очистить: вызывает forget flow, очищает server pings и selected server;- click по server row: вызывает
selectSingBoxServer, выставляет dirty state; Ping все: вызываетpingAllSingBoxServers;- per-server ping: вызывает существующий
pingSingBoxServer(tag), если добавляем кнопку/иконку в row; Конфиг: вызываетgenerateSingBoxConfig;Применить маршрут: вызывает общийupdateConfig.
Анимации:
- mode switch меняет активный segment без скачка высоты;
- при смене mode panel content cross-fade;
- ping badge показывает loading spinner только на проверяемых row;
- server row после ping обновляет latency с короткой подсветкой;
- subscription/server empty state появляется fade-in;
- generated config success подсвечивает config path на 400-600ms.
Задачи исполнения
Задача 1: Ввести shell вкладок и производные view models
Разрешенные файлы:
apps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.css
Ожидаемый результат:
activePanel: 'summary' | 'proxifyre' | 'proxy'.- Общий header с tab control.
- Производные функции для summary: system status, route label, endpoint label, config labels, app count, issue list.
- Старые JSX-блоки временно остаются, но render path начинает разделяться.
Проверка:
cd apps/windows-client && npm run build
Приемочные доказательства:
- Screenshot/state показывает три tab buttons и корректную активную вкладку.
Параллельное выполнение: нет, общий App.tsx.
Задача 2: Реализовать read-only панель Сводка
Разрешенные файлы:
apps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.css
Ожидаемый результат:
- Summary panel без input/apply/install/start/stop/delete.
- Статус системы, ProxiFyre, подключение, маршрут, активный server, apps count, config paths, dirty state.
- Навигационные клики по read-only строкам переводят на соответствующие вкладки.
Проверка:
cd apps/windows-client && npm run build- Manual DOM/visual check: на summary нет изменяющих controls.
Приемочные доказательства:
- Screenshot summary panel.
- Запись в evidence: какие элементы read-only и куда ведут navigation clicks.
Параллельное выполнение: нет.
Задача 3: Перенести ProxiFyre и список приложений во вторую панель
Разрешенные файлы:
apps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.css
Ожидаемый результат:
- ProxiFyre panel содержит status card, setup details, service actions, app add/remove, generated config path и apply/open config actions.
- Существующие handlers переиспользованы без изменения backend ownership.
hasUnappliedChangesпродолжает работать после add/remove.
Проверка:
cd apps/windows-client && npm run build
Приемочные доказательства:
- Screenshot ProxiFyre panel с service status и apps list.
- Проверка add/remove вызывает dirty state.
Параллельное выполнение: нет.
Задача 4: Перенести VPN/Proxy route settings в третью панель
Разрешенные файлы:
apps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.cssapps/windows-client/src/api/tauriCommands.ts, если нужен внешний target ping.apps/windows-client/src/domain/types.ts, если нужен внешний target ping DTO.
Ожидаемый результат:
- VPN/Proxy panel содержит route mode switch, external proxy editor, Local sing-box controls, subscription, server selection, ping, generate config, route preview и apply.
- Внешний proxy path не зависит от Local sing-box.
- Local sing-box UI не показывается на summary и не смешивается с ProxiFyre panel.
Проверка:
cd apps/windows-client && npm run build
Приемочные доказательства:
- Screenshot external proxy mode.
- Screenshot local proxy mode с server list или empty state.
Параллельное выполнение: нет.
Задача 5: Добавить или переиспользовать проверку доступности внешнего proxy target
Разрешенные файлы:
apps/windows-client/src-tauri/src/commands.rsapps/windows-client/src-tauri/src/main.rsapps/windows-client/src/api/tauriCommands.tsapps/windows-client/src/domain/types.tsapps/windows-client/src-tauri/tests/command_tests.rsили отдельный focused test.
Ожидаемый результат:
- Если существующих данных недостаточно для "все ли окей с подключением" во внешнем proxy mode, добавить typed command наподобие
ping_proxy_target. - Command делает TCP connect check к host/port с timeout, возвращает
{ ok, latency, error }. - UI отображает результат в VPN/Proxy panel и summary.
- Это не заменяет apply и не пишет source config.
Проверка:
cd apps/windows-client/src-tauri && cargo test commandcd apps/windows-client && npm run build
Приемочные доказательства:
- Test или manual state показывает успешный/ошибочный result shape.
Параллельное выполнение: частично, если UI DTO names согласованы заранее; интеграция не parallel-safe.
Задача 6: Привести CSS, анимации и responsive behavior
Разрешенные файлы:
apps/windows-client/src/styles/app.cssapps/windows-client/src/app/App.tsx, только className/ARIA adjustments.
Ожидаемый результат:
- Tab bar, panel transitions, setup expand/collapse, ping badges, dirty/apply bar и responsive grids.
- Нет перекрытия текста, длинные paths/servers переносятся.
- Mobile layout: tabs не ломаются, server list минимум 2 колонки или 1 колонка на очень узком экране, command row складывается.
prefers-reduced-motionотключает декоративные transitions.
Проверка:
cd apps/windows-client && npm run build- Browser/Tauri visual check на desktop и узком viewport.
Приемочные доказательства:
- Screenshots desktop + narrow viewport.
Параллельное выполнение: нет, потому что зависит от финальной разметки.
Задача 7: Финальная проверка и evidence
Разрешенные файлы:
docs/goals/windows-client-three-panel-ui/EVIDENCE.md- При необходимости
apps/windows-client/README.md, если нужно зафиксировать новую навигацию.
Ожидаемый результат:
- Evidence содержит commands, результаты build/tests, screenshots/state checks и список остаточных рисков.
- Если Tauri service actions не проверялись на реальной Windows elevated среде, это явно помечено как
implemented but unprovenтолько для service lane.
Проверка:
git status --shortcd apps/windows-client && npm run buildcd apps/windows-client/src-tauri && cargo test, если Rust command менялся.
Приемочные доказательства:
- Summary read-only verified.
- ProxiFyre actions verified.
- VPN/Proxy route switch and ping states verified.
- No root web/server changes.
Параллельное выполнение: нет.
Prompt для PRE review
Использовать C:\Users\PC\.agents\skills\krypton-planning\plan-reviewer-prompt.md со следующими данными:
Файл плана:
docs/goals/windows-client-three-panel-ui/PLAN.md
Исходный запрос:
- Разбить Windows client UI на три переключаемые панели: общая read-only сводка, настройки ProxiFyre, настройки VPN/proxy; подробно описать внешний вид, анимации и действия.
Контракт результата:
- Пользователь сначала видит статус системы и примененный route/config без изменения данных, затем переходит в нужную панель для ProxiFyre или VPN/proxy действий.
Архитектурный срез:
- Основной scope:
apps/windows-client/src/app/App.tsxиapps/windows-client/src/styles/app.css; backend только для внешнего target ping, если текущих команд недостаточно.
Требование к приемочным доказательствам:
- Build/tests плюс screenshots/state proof трех панелей и read-only summary.
Известные non-goals:
- Не менять root
src/web/src/server. - Не переписывать Tauri backend без нужды.
- Не добавлять скрытую установку компонентов.
- Не делать summary редактируемой.
Опасные пути или слои:
- Дублирование source of truth в React.
- Изменение generated config напрямую.
- Смешивание Local sing-box controls обратно в ProxiFyre panel.
- Потеря external proxy path как полноценного режима.