Files
avandClaude Opus 4.8 4e2593ac31 Перенос дизайна в server-rendered веб-UI (web-ui)
Новая capability web-ui: презентационный перенос готового дизайна
(семантический HTML + единый jellybit.css, тёмная тема по настройке ОС)
в html/template без шага сборки.

- Встроенная (go:embed) отдача статики под /static с Cache-Control и
  cache-busting (?v=<hash> по содержимому css/js).
- Шрифты IBM Plex self-hosted (@font-face, cyrillic+latin), без CDN.
- Наколеночный менеджер зависимостей: вендор (htmx + шрифты) не хранится
  в репо (gitignore), идемпотентно добывается `task assets` по
  web/assets.manifest с проверкой sha256; task build/run зависят от assets.
- Общие партиалы: шапка, бейдж статуса (карта всех 14 состояний),
  виджет «файл источника → раскладка» (общий для review и download).
- Страницы: список с фильтром/поиском, ревью, новая страница просмотра
  загрузки (/download/{id}). deleted скрыт по умолчанию.
- Превью раскладки берётся из единой логики internal/layout
  (buildFileRows), без дублирования правил имён в шаблонах.
- Убраны meta-refresh и инлайн-стили; copyHash на vanilla с fallback
  на execCommand и честной индикацией (целевой деплой — HTTP LAN).

Вне scope (отдельный change): живые обновления прогресса и раздел
раздачи, клиентский режим ручной раскладки файл→серия (с Alpine.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:59:19 +03:00

9.0 KiB
Raw Permalink Blame History

ADDED Requirements

Requirement: Встроенная отдача статики

Сервис SHALL отдавать статические ассеты (CSS, клиентский JS, вендорные библиотеки, шрифты) из встроенной (go:embed) файловой системы под префиксом /static/, без внешних зависимостей времени выполнения. Бинарь остаётся единым и самодостаточным.

Scenario: Запрос встроенного ассета

  • WHEN клиент запрашивает GET /static/css/jellybit.css
  • THEN сервис отвечает 200 с телом из встроенной FS и корректным Content-Type

Scenario: Кэширование статики

  • WHEN сервис отдаёт ответ на запрос под /static/
  • THEN ответ содержит заголовок Cache-Control, разрешающий кэширование ассета браузером

Scenario: Несуществующий ассет

  • WHEN клиент запрашивает несуществующий путь под /static/
  • THEN сервис отвечает 404 и не раскрывает структуру файловой системы

Requirement: Шрифты без внешних сетей

Веб-UI SHALL подключать шрифты (IBM Plex Sans, IBM Plex Mono) только из локально встроенных файлов через @font-face. Страницы MUST NOT обращаться к сторонним хостам (Google Fonts CDN и т. п.) для загрузки шрифтов или стилей.

Scenario: Нет внешних ссылок на шрифты

  • WHEN браузер открывает любую страницу веб-UI
  • THEN все используемые шрифты загружаются из-под /static/ того же origin, без обращений к внешним доменам

Requirement: Единая дизайн-система

Все страницы веб-UI SHALL использовать единственный CSS-файл jellybit.css с дизайн-токенами; страницы MUST NOT содержать инлайн-<style> или хардкод цветов вне токенов. Тема (светлая/тёмная) SHALL определяться настройкой ОС (color-scheme + prefers-color-scheme), без отдельного переключателя.

Scenario: Тёмная тема по настройке ОС

  • WHEN в ОS пользователя выбрана тёмная тема и открывается страница
  • THEN интерфейс отображается в тёмной палитре из токенов, без действий пользователя

Scenario: Нет инлайн-стилей

  • WHEN рендерится любая страница веб-UI
  • THEN оформление берётся из подключённого jellybit.css, в разметке нет блоков <style> с хардкодом цветов

Requirement: Бейдж статуса загрузки

Веб-UI SHALL отображать состояние каждой загрузки бейджем <span class="badge st-{STATE}"> с человекочитаемой русской подписью; класс определяет цвет группы. Маппинг SHALL покрывать все состояния домена (downloading, completed, recognizing, linking, review, deferred, done, stuck, target_missing, failed, orphaned, cancelled, reverted, deleted).

Scenario: Состояние отрисовано бейджем

  • WHEN загрузка находится в состоянии review
  • THEN в списке у неё бейдж с классом st-review и подписью «на ревью»

Scenario: Полнота покрытия

  • WHEN загрузка находится в любом из состояний домена
  • THEN для него существует класс бейджа и русская подпись (неизвестных состояний без оформления нет)

Requirement: Страницы веб-UI

Веб-UI SHALL предоставлять страницы: список загрузок с единым окном добавления и фильтром/поиском (/), экран ревью одной загрузки (/review/{id}) и страницу просмотра одной загрузки (/download/{id}) с распознаванием, файлами→раскладкой и историей. Состояние deleted SHALL быть скрыто в списке по умолчанию (с переключателем «показать всё»). (Раздел живой статистики раздачи на странице загрузки — вне scope этого change, вводится вместе с живыми обновлениями.)

Scenario: Просмотр одной загрузки

  • WHEN клиент открывает GET /download/{id} существующей загрузки
  • THEN отрисовывается страница с её распознаванием, файлами, раскладкой и историей

Scenario: Удалённые скрыты по умолчанию

  • WHEN в списке есть загрузки в состоянии deleted и фильтр «показать всё» не включён
  • THEN они не отображаются, но доступны при включённом переключателе

Requirement: Действия соответствуют состоянию

Каждая страница SHALL показывать только действия, допустимые в текущем состоянии загрузки, и каждое действие-кнопка SHALL отправлять форму с полями, имена которых совпадают с ожидаемыми обработчиком (internal/httpapi).

Scenario: Набор действий по состоянию

  • WHEN загрузка в состоянии done
  • THEN доступно действие отката (undo), но недоступны «применить»/«позже»

Scenario: Имена полей формы

  • WHEN пользователь отправляет форму действия (например, «уточнить»)
  • THEN поля формы имеют name, которые обработчик читает без переименования, и действие исполняется

Requirement: Превью раскладки через единую логику именования

Превью целевых путей раскладки в веб-UI SHALL вычисляться той же логикой именования, что и реальная раскладка (internal/naming), а не дублировать правила в шаблоне. Показанные пути MUST совпадать с теми, что создались бы при применении.

Scenario: Превью совпадает с реальной раскладкой

  • WHEN на экране ревью отображается превью целевых путей для текущей догадки
  • THEN эти пути идентичны тем, что создаст применение (те же правила имён, спецвыпусков, мультифайла, запрещённых символов и коллизий)

Requirement: Клиентские взаимодействия без сборки

Веб-UI SHALL реализовывать клиентскую логику без шага сборки и без реактивных фреймворков: копирование infohash (vanilla JS) и раскрытие контекста нативным <details>. Все действия над загрузкой SHALL выполняться через формы/htmx (раундтрип на сервер), без клиентского пересчёта доменного состояния.

Scenario: Копирование infohash

  • WHEN пользователь нажимает кнопку копирования рядом с infohash
  • THEN значение infohash копируется в буфер обмена без перезагрузки страницы

Scenario: Раскрытие контекста без JS

  • WHEN пользователь раскрывает спойлер переданного контекста
  • THEN контекст показывается нативным <details>, без скриптов