Files
ds-galo/openspec/changes/archive/2026-10-23-photo-curve-presets/proposal.md
T

6.0 KiB
Raw Blame History

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 сохранения пресетов в профиле.