74 lines
6.0 KiB
Markdown
74 lines
6.0 KiB
Markdown
# Proposal
|
||
|
||
## Why
|
||
|
||
Тоновая кривая сейчас ведёт себя не как инструмент из Lightroom: крайние узлы не
|
||
существуют до первых кликов, линия строится по прямым сегментам, а готовых
|
||
пресетов контраста и пользовательских пресетов нет. Пользователь не может быстро
|
||
применить типовой контраст или сохранить свою кривую. Дополнительно
|
||
`PATCH /auth/me/preferences` заменяет весь объект настроек, поэтому хранение
|
||
пресетов в профиле без мержа затирало бы другие разделы.
|
||
|
||
## What Changes
|
||
|
||
- **Кривая.** Крайние узлы `(0,0)` и `(1,1)` существуют сразу и являются обычными
|
||
точками; первый клик добавляет точку между ними. Крайние узлы двигаются по x и
|
||
y, вне них кривая постоянна («полки», как на скрине). Линия и рендер используют
|
||
плавную монотонную кубическую интерполяцию (PCHIP): SVG-путь и LUT в Go/TS.
|
||
«Сбросить» возвращает линейную кривую.
|
||
- **Встроенные пресеты.** `Линейный`, `Средний контраст`, `Сильный контраст` —
|
||
каждый описывает все четыре канала: контраст задаётся кривой RGB, каналы
|
||
R/G/B остаются линейными. Подпись показывает активный пресет; при ручной
|
||
правке любого канала — `Пользовательский`.
|
||
- **Пользовательские пресеты.** Пресет описывает кривые всех каналов
|
||
(`name`, `channels: { rgb, red, green, blue }`). Сохранение текущих кривых
|
||
всех каналов, применение заменяет все четыре кривые, переименование и
|
||
удаление. Хранение в `users.preferences.curve_presets` (профиль пользователя),
|
||
приватно для пользователя.
|
||
- **Мерж настроек.** `PATCH /auth/me/preferences` принимает `photo_info` и
|
||
`curve_presets` по отдельности, мержит переданные разделы с сохранёнными,
|
||
валидирует и возвращает полный merged-объект. Сохранение «Сведений» больше не
|
||
затирает пресеты, и наоборот.
|
||
- **Импорт/экспорт.** JSON-файл `{ version: 1, presets: [...] }`: экспорт
|
||
пользовательских пресетов, импорт с добавлением в профиль (при совпадении имени
|
||
— перезапись).
|
||
- **Совместимость.** Миграций схемы нет: пресеты лежат в JSON-блобе
|
||
`preferences`. Старые пресеты формата `{ channel, points }` конвертируются в
|
||
четыре канала при чтении и перезаписываются при следующем сохранении.
|
||
Существующие сохранённые кривые начнут интерполироваться плавно, поэтому их
|
||
визуальный результат может немного измениться.
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
|
||
Нет — поведение входит в существующие способности `photos` и `auth`.
|
||
|
||
### Modified Capabilities
|
||
|
||
- `photos`: добавляются требования «Тоновая кривая» (крайние узлы, плавная
|
||
интерполяция, встроенные пресеты, сброс) и «Пользовательские пресеты кривой»
|
||
(пресет из четырёх каналов, сохранение/применение/переименование/удаление,
|
||
импорт/экспорт).
|
||
- `auth`: требование «Хранение пользовательских настроек интерфейса»
|
||
расширяется мержем разделов и хранением пользовательских пресетов кривой;
|
||
добавляется сценарий «сохранение одного раздела не затирает другие».
|
||
|
||
## Impact
|
||
|
||
- `backend/internal/auth/handlers.go` — `preferencesPayload` с `curve_presets`,
|
||
мерж разделов, валидация имени и кривых всех четырёх каналов.
|
||
- `backend/internal/auth/store.go` / `sqlite_store.go` — без изменений схемы;
|
||
запись merged-JSON через существующий `UpdatePreferences`.
|
||
- `backend/internal/photos/edit.go` — `curveEval`/`curveLUT` переходят на PCHIP;
|
||
тесты Go на гладкость/LUT.
|
||
- `frontend/src/lib/edit.ts` — PCHIP в `buildCurveLUT`, типы и нормализация
|
||
пресетов, точки кривой.
|
||
- `frontend/src/lib/components/PhotoEditPanel.svelte` — узлы-углы, плавный SVG-путь,
|
||
меню пресетов, сохранение/переименование/удаление, импорт/экспорт.
|
||
- `frontend/src/lib/types.ts`, `stores/auth.svelte.ts`, `api.ts` — тип
|
||
`Preferences.curve_presets`, сохранение через существующий endpoint.
|
||
- Новые вспомогательные модули: меню/диалоги пресетов, импорт/экспорт JSON.
|
||
- Тесты: `edit_test.go`, `edit.test.ts`, тесты мержа/валидации preferences,
|
||
e2e сохранения пресетов в профиле.
|