Files
harbor-net/docs/goals/windows-client-three-panel-ui/PLAN.md

424 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План реализации трехпанельного интерфейса 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 как полноценного режима.