diff --git a/openspec/specs/dev-make-workflow/spec.md b/openspec/specs/dev-make-workflow/spec.md index 376a808..1589260 100644 --- a/openspec/specs/dev-make-workflow/spec.md +++ b/openspec/specs/dev-make-workflow/spec.md @@ -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** собранный модуль фильтров присутствует в нём diff --git a/openspec/specs/media-objects/spec.md b/openspec/specs/media-objects/spec.md index 3e8004e..2cf5d8b 100644 --- a/openspec/specs/media-objects/spec.md +++ b/openspec/specs/media-objects/spec.md @@ -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 менять привязку, а объекты diff --git a/openspec/specs/photos/spec.md b/openspec/specs/photos/spec.md index fb02663..7e278a5 100644 --- a/openspec/specs/photos/spec.md +++ b/openspec/specs/photos/spec.md @@ -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** исходный объект и его варианты остаются неизменными diff --git a/openspec/specs/ui-workspace/spec.md b/openspec/specs/ui-workspace/spec.md index 8f34cf8..3ef4614 100644 --- a/openspec/specs/ui-workspace/spec.md +++ b/openspec/specs/ui-workspace/spec.md @@ -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** блок «Кривая» свёрнут, кнопки выбора канала доступны, а по клику на заголовок + график разворачивается и сворачивается обратно