# План реализации трехпанельного интерфейса 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.md` - `docs/goals/windows-client-three-panel-ui/GOAL.md` - `docs/goals/windows-client-three-panel-ui/EVIDENCE.md` Файлы для изменения: - `apps/windows-client/src/app/App.tsx` - `apps/windows-client/src/styles/app.css` - `apps/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.json` - `C:\ProgramData\VpnProxy\config\targets.json` - `C:\ProgramData\VpnProxy\config\components.json` - `C:\ProgramData\VpnProxy\config\local-singbox.json` - `C:\ProgramData\VpnProxy\state\singbox-subscription-cache.json` - `C:\ProgramData\VpnProxy\state\activity.json` Производные артефакты: - `C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json` - `C:\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: reduce` transition отключается; - 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-card` pattern, 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.tsx` - `apps/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.tsx` - `apps/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.tsx` - `apps/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.tsx` - `apps/windows-client/src/styles/app.css` - `apps/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.rs` - `apps/windows-client/src-tauri/src/main.rs` - `apps/windows-client/src/api/tauriCommands.ts` - `apps/windows-client/src/domain/types.ts` - `apps/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 command` - `cd 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.css` - `apps/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 --short` - `cd apps/windows-client && npm run build` - `cd 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 как полноценного режима.