docs(openspec): описать правки редактора, сделанные без спецификаций

Дополнены спеки ui-workspace (сворачивание кривой, живая гистограмма,
точки кривой, навигация в зуме, Space к центру), media-objects (роли edit*,
привязка отредактированной версии, отдельная очередь рендера правок),
photos (рендер по оригиналу) и dev-make-workflow (сборка WASM-модуля).
This commit is contained in:
iu
2026-10-21 20:21:59 +03:00
parent eb2d478275
commit 748143c9d7
4 changed files with 103 additions and 20 deletions
+19
View File
@@ -53,3 +53,22 @@ Android-клиента и устанавливает его на выбранн
#### Scenario: Явная цель
- **WHEN** `make` запущен с именем цели, например `make frontend`
- **THEN** выполняется именно эта цель
### Requirement: Сборка WASM-модуля фильтров
Фильтры правок в браузере SHALL считаться WASM-модулем, собираемым из исходников на
Rust в каталоге `frontend/wasm/light`. Сборка фронтенда SHALL обновлять модуль перед
сборкой статики. Если инструмент сборки модуля недоступен, SHALL использоваться готовый
модуль из репозитория, а сборка SHALL NOT прерываться. Готовый модуль SHALL храниться
в репозитории, чтобы фронтенд собирался без Rust-инструментов.
#### Scenario: Сборка фронтенда с модулем
- **WHEN** выполняется сборка фронтенда
- **THEN** перед сборкой статики обновляется WASM-модуль фильтров
#### Scenario: Нет Rust-инструментов
- **WHEN** инструмент сборки модуля недоступен
- **THEN** используется готовый модуль из репозитория, а сборка завершается успешно
#### Scenario: Готовый модуль в репозитории
- **WHEN** репозиторий проверяется на чистоту
- **THEN** собранный модуль фильтров присутствует в нём
+28 -3
View File
@@ -25,7 +25,8 @@
Каждый физический объект SHALL иметь ровно одну запись в слое метаданных с ключом,
MIME-типом, размером, габаритами и состоянием; фото SHALL ссылаться на объекты по
ролям original, thumb, medium, preview и playback.
ролям original, thumb, medium, preview, playback, edit, edit_thumb, edit_medium и
edit_preview.
#### Scenario: Привязка ролей
@@ -42,10 +43,18 @@ MIME-типом, размером, габаритами и состоянием;
- **WHEN** видео обработано
- **THEN** медиа ссылается на объект playback наряду с оригиналом и постером
#### Scenario: Привязка отредактированной версии
- **WHEN** фото отредактировано и отредактированная версия отрендерена
- **THEN** фото ссылается на объекты edit, edit_thumb, edit_medium и edit_preview рядом с
исходными вариантами
### Requirement: Совместные объекты
Несколько фото SHALL иметь возможность ссылаться на один и тот же физический
объект; перенос и копирование SHALL изменять только ссылки и SHALL не изменять
объекты хранилища.
объекты хранилища. Отредактированная версия SHALL создаваться и привязываться только
к тому фото, чьи правки её породили, в отличие от обычных вариантов, которые
разделяются копиями того же оригинала.
#### Scenario: Копирование
- **WHEN** пользователь копирует фото в другой альбом
@@ -55,6 +64,16 @@ MIME-типом, размером, габаритами и состоянием;
- **WHEN** пользователь переносит фото в другой альбом
- **THEN** изменяется только привязка к альбому, объекты хранилища не меняются
#### Scenario: Правка не распространяется на копии
- **WHEN** фото скопировали в другой альбом, а затем отредактировали исходное фото
- **THEN** отредактированные объекты привязаны только к отредактированному фото, а копия
остаётся в исходном виде
#### Scenario: Копия отредактированного фото
- **WHEN** фото с уже отрендеренной отредактированной версией копируют в другой альбом
- **THEN** копия разделяет те же объекты, включая отредактированные, но не наследует
параметры правок
### Requirement: Сборка мусора по ссылкам
Объект хранилища SHALL удаляться только когда на него не ссылается ни одно фото и ни один
аватар пользователя; удаление альбома и попадание фото в корзину SHALL сохранять объекты.
@@ -93,7 +112,9 @@ MIME-типом, размером, габаритами и состоянием;
однократным выполнением и повтором при сбое; готовый результат SHALL
транслироваться подписчикам альбома. Очередь SHALL поддерживать настраиваемую
пропускную способность, SHALL обрабатывать более свежие фото раньше остальных и
SHALL различать короткие задания изображений и длительные задания видео.
SHALL различать короткие задания изображений и длительные задания видео. Рендер
отредактированных версий SHALL использовать отдельную очередь, чтобы правки не
блокировали генерацию обычных вариантов.
#### Scenario: Повтор после рестарта
- **WHEN** процесс перезапускается с незавершёнными заданиями
@@ -115,6 +136,10 @@ SHALL различать короткие задания изображений
- **WHEN** выполняется длительная подготовка видео
- **THEN** задание удерживается на весь срок выполнения и не вытесняет генерацию вариантов изображений
#### Scenario: Рендер правок не блокирует варианты
- **WHEN** в фоне выполняется рендер отредактированной версии
- **THEN** генерация обычных вариантов продолжается независимо от него
### Requirement: Аватар пользователя как объект журнала
Аватар пользователя SHALL храниться как объект журнала, привязанный к пользователю по ролям,
соответствующим нарезкам аватара. Замена и удаление аватара SHALL менять привязку, а объекты
+8 -3
View File
@@ -286,9 +286,10 @@ SHALL быть доступно и для фото без альбома (нап
Система SHALL поддерживать неразрушающее редактирование фотографий. Параметры правок
SHALL храниться в метаданных фото, а отредактированная версия SHALL создаваться как
отдельные объекты (роли `edit`, `edit_thumb`, `edit_medium`, `edit_preview`) рядом с
исходными вариантами. Исходный объект SHALL оставаться неизменным, а скачивание SHALL
отдавать оригинал. Сброс правок SHALL удалять и параметры, и отредактированную версию.
Правки SHALL применять только к изображениям.
исходными вариантами. Рендер SHALL выполняться по исходному объекту фото, а не по
его уменьшенным вариантам. Исходный объект SHALL оставаться неизменным, а скачивание
SHALL отдавать оригинал. Сброс правок SHALL удалять и параметры, и отредактированную
версию. Правки SHALL применять только к изображениям.
#### Scenario: Сохранение правок
- **WHEN** пользователь сохраняет правки фото
@@ -298,6 +299,10 @@ SHALL храниться в метаданных фото, а отредакти
- **WHEN** правки фото сохранены
- **THEN** система готовит варианты сетки и полноразмерную версию в фоне и сообщает о готовности
#### Scenario: Рендер по оригиналу
- **WHEN** готовится отредактированная версия фото
- **THEN** правки применяются к пикселям исходного объекта, а не к его уменьшенной копии
#### Scenario: Неразрушачность
- **WHEN** фото отредактировано
- **THEN** исходный объект и его варианты остаются неизменными
+48 -14
View File
@@ -263,9 +263,9 @@ SHALL выдвигать правую панель поверх содержим
Просмотр SHALL поддерживать зум колесом мыши без прокрутки, с привязкой к указателю и
верхним пределом 200% размеров фото. Клавиши `+` и `-` SHALL менять масштаб на шаг, сохраняя
точку в центре просмотра. `Space` SHALL возвращать изображение из любого зума во
вписанный вид, а из вписанного — в 100%. При зуме SHALL догружаться оригинал изображения.
Стрелки соседних фото SHALL появляться у левой/правой кромки и прятаться в зуме. Зум SHALL
работать и в полноэкранном режиме.
вписанный вид, а из вписанного — в 100% от оригинала с центрированием по центру кадра.
При зуме SHALL догружаться оригинал изображения. Зум SHALL работать и в полноэкранном
режиме.
#### Scenario: Зум колесом к указателю
- **WHEN** пользователь вращает колесо мыши над фото
@@ -278,16 +278,27 @@ SHALL выдвигать правую панель поверх содержим
#### Scenario: Пробел
- **WHEN** пользователь нажимает `Space`
- **THEN** из вписанного вида изображение переходит в 100%, а из любого зума возвращается во вписанный
- **THEN** из вписанного вида изображение переходит в 100% от оригинала по центру кадра, а из
любого зума возвращается во вписанный
#### Scenario: Оригинал в зуме
- **WHEN** пользователь входит в зум
- **THEN** догружается оригинал изображения и подменяется по факту загрузки
### Requirement: Навигация в зуме
Стрелки соседних фото SHALL появляться у левой/правой кромки и прятаться в зуме. Клавиши
со стрелками в зуме SHALL перемещать изображение, а переключение соседних фото SHALL
оставаться за мышью и кнопками у краёв. В зуме пользователь SHALL перемещать изображение
перетаскиванием и прокруткой.
#### Scenario: Стрелки соседних фото
- **WHEN** курсор находится у левой или правой кромки области просмотра
- **THEN** показывается соответствующая стрелка, скрываясь сразу после ухода; в зуме стрелки скрыты
#### Scenario: Стрелки в зуме
- **WHEN** фото увеличено, и пользователь жмёт стрелки клавиатуры
- **THEN** изображение перемещается, а переключение соседних фото не происходит
#### Scenario: Панорамирование
- **WHEN** фото увеличено
- **THEN** пользователь может перемещать изображение перетаскиванием и прокруткой
@@ -779,27 +790,28 @@ SHALL очищаться. При отсутствии сети приложен
### Requirement: Вкладка «Редактирование»
Правая панель фото SHALL содержать вкладку «Редактирование» с инструментом «Свет»:
ползунки экспозиции, контраста, светов, теней, белых и чёрных, а также точечную кривую
с выбором канала. График кривой SHALL показывать гистограмму каналов фото: выбранный
канал — своим цветом, мастер-канал — всеми тремя. Правки SHALL применяться к фото сразу и
отправляться на сервер после десяти секунд без изменений либо при переключении фото.
Переключатель «Сброс» SHALL удалять параметры правок и отредактированную версию фото.
Сетка и просмотр SHALL показывать отредактированную версию фото, когда она отрендерена.
#### Scenario: Отложенная отправка
- **WHEN** пользователь меняет ползунок и не трогает панель десять секунд
- **THEN** правки отправляются на сервер, а сервер рендерит фото в фоне
с выбором канала. Правки SHALL применяться к фото сразу и отправляться на сервер после
десяти секунд без изменений либо при переключении фото. Переключатель «Сброс» SHALL
удалять параметры правок и отредактированную версию фото. Сетка и просмотр SHALL
показывать отредактированную версию фото, когда она отрендерена. Обновление фото SHALL
сохранять открытую вкладку панели.
#### Scenario: Вкладки панели
- **WHEN** открыта правая панель фото
- **THEN** видны вкладки «Сведения» и «Редактирование»
#### Scenario: Отложенная отправка
- **WHEN** пользователь меняет ползунок и не трогает панель десять секунд
- **THEN** правки отправляются на сервер, а сервер рендерит фото в фоне
#### Scenario: Сохранение правок
- **WHEN** пользователь отпускает ползунок
- **THEN** правки сохраняются, а после рендера фото в сетке и просмотре показывается отредактированная версия
#### Scenario: Правки видны сразу
- **WHEN** пользователь меняет ползунок, а сервер ещё не отрендерил фото
- **THEN** видимая область фото в просмотре показывает правки без ожидания рендера
- **THEN** видимая область фото в просмотре показывает правки без ожидания рендера — и во
вписанном виде, и в зуме
#### Scenario: Фильтры считаются в браузере
- **WHEN** браузер рисует предпросмотр правок
@@ -812,3 +824,25 @@ SHALL очищаться. При отсутствии сети приложен
#### Scenario: Зум при правках
- **WHEN** фото отредактировано, и пользователь увеличивает его
- **THEN** браузер рисует видимую область с правками, пока сервер не отрендерил фото, а зум не сбрасывается при обновлении фото
### Requirement: График тональной кривой
График кривой SHALL показывать гистограмму каналов фото: выбранный канал — своим
цветом, мастер-канал — всеми тремя. Гистограмма SHALL пересчитываться с учётом
текущих правок. Точки кривой SHALL добавляться кликом по полю графика, перетаскиваться
и перемещаться стрелками клавиатуры. Блок «Кривая» SHALL сворачиваться и разворачиваться
по клику на заголовок, по умолчанию SHALL быть свёрнут, а кнопки выбора канала SHALL
оставаться доступными.
#### Scenario: Живая гистограмма
- **WHEN** пользователь двигает ползунок или точку кривой
- **THEN** гистограмма на графике пересчитывается с учётом текущих правок
#### Scenario: Точки кривой
- **WHEN** пользователь кликает по полю графика, перетаскивает точку или жмёт стрелки с
фокусом на точке
- **THEN** точка добавляется, перемещается и меняет кривую
#### Scenario: Сворачивание кривой
- **WHEN** пользователь открывает инструмент «Свет»
- **THEN** блок «Кривая» свёрнут, кнопки выбора канала доступны, а по клику на заголовок
график разворачивается и сворачивается обратно