feat(photos): добавить пресеты кривой и починить переключение фото

- PCHIP для предпросмотра и серверного рендера
- пресеты всех каналов в профиле, импорт и экспорт
- мерж настроек auth без потери разделов
- сохранение вкладки и правок текущего фото при переключении
This commit is contained in:
iu
2026-10-23 22:56:55 +03:00
parent 3b8406fb4c
commit 0bfee5f2f8
20 changed files with 2127 additions and 105 deletions
@@ -0,0 +1,49 @@
# Tasks
## 1. Общая математика кривой (TS + Go)
- [x] 1.1 Заменить линейную интерполяцию в `frontend/src/lib/edit.ts` на монотонный кубический Эрмит (PCHIP): наклоны, касательные, оценка между точками, плоские участки вне крайних — проверить `npm run test` (`edit.test.ts`, значения LUT и монотонность)
- [x] 1.2 Повторить ту же формулу в `backend/internal/photos/edit.go` (`curveEval`/`curveLUT`) — проверить `go test ./internal/photos/ -run TestCurve -v`
- [x] 1.3 Сверить Go и TS на нескольких кривых (линейная, средний/сильный контраст, кривая с крайними внутри) захардкоженными значениями LUT — проверить оба набора тестов
## 2. Backend: мерж настроек и пресеты
- [x] 2.1 Расширить `preferencesPayload` в `backend/internal/auth/handlers.go` полем `curve_presets` и валидацией (лимит количества, имя 1..64, 2..16 точек на канал, x/y в 0..1) — проверить `go test ./internal/auth/ -v`
- [x] 2.2 Сделать серверный мерж разделов: читать текущие `preferences`, мержить `photo_info`/`curve_presets`, писать и возвращать merged-объект — проверить тестом «сохранение photo_info не затирает пресеты и наоборот»
- [x] 2.3 Добавить e2e-проверку сохранения пресетов в профиле и их приватности — проверить `go test ./internal/e2e/ -run TestCurvePresets -v`
## 3. UI: узлы и плавная кривая
- [x] 3.1 Показывать крайние точки `(0,0)` и `(1,1)` по умолчанию; первый клик вставляет точку между ними; крайние двигаются по x/y, вне них — плоские участки — проверить вручную и `npm run check`
- [x] 3.2 Рисовать SVG-путь кубическими Безье по тем же касательным (плоские сегменты до/после крайних) — проверить визуально, что линия плавная
- [x] 3.3 Сохранить клавиатурную правку точек, двойной клик-сброс и ограничение x между соседями — проверить `npm run check` и ручным сценарием
## 4. UI: пресеты и файлы
- [x] 4.1 Заменить статичный «Линейный» на меню встроенных пресетов (`Линейный`, `Средний контраст`, `Сильный контраст`) с активной подписью/«Пользовательский» — проверить `npm run check`
- [x] 4.2 Добавить тип `Preferences.curve_presets` и сохранение/применение/переименование/удаление пользовательских пресетов через существующий endpoint — проверить `npm run test` и сохранение в профиле
- [x] 4.3 Реализовать импорт/экспорт JSON `{ version: 1, presets: [...] }` с валидацией и upsert по имени — проверить ручным импортом/экспортом и `npm run check`
## 5. Интеграция и проверка
- [x] 5.1 Прогнать `npm run check`, `npm run test`, `go test ./...`, `make build` — всё зелёное
- [x] 5.2 Проверить, что WebGL и WASM используют новый LUT, а старые сохранённые кривые рендерятся плавно без миграции данных — визуально и тестами
- [x] 5.3 Проверить приватность и лимиты пресетов (чужой профиль, слишком длинное имя, >16 точек) — тестами `internal/auth`/`internal/e2e`
## 6. Правка: пресет описывает все каналы
- [x] 6.1 Обновить `CurvePreset` в `frontend/src/lib/types.ts` и `curve-presets.ts`: `channels` для RGB/R/G/B, встроенные пресеты и поиск активного пресета по всем каналам — проверить `npm run test`
- [x] 6.2 Обновить серверную модель и валидацию `curve_presets` в `backend/internal/auth/handlers.go`: объект `channels` со всеми четырьмя каналами — проверить `go test ./internal/auth/ -v`
- [x] 6.3 Обновить сохранение и применение в `PhotoEditPanel.svelte` и `CurvePresetMenu.svelte`: сохранять и заменять все четыре канала, не переключать текущий канал — проверить `npm run check`
- [x] 6.4 Обновить импорт/экспорт и совместимость со старым форматом `{name, channel, points}`, тесты и e2e — проверить `npm run test` и `go test ./internal/e2e/ -run TestCurvePresets -v`
## 7. Переключение фото
- [x] 7.1 Сохранять вкладку правой панели при смене фото, вынеся её состояние в `AlbumPanel` — проверить в браузере
- [x] 7.2 Исправить регистрацию cleanup в `PhotoEditPanel`, чтобы накопленные правки отправлялись при переключении — проверить в браузере
- [x] 7.3 Защитить панель от устаревших ответов сохранения/загрузки и кратковременного `photo = null` — проверить `npm run check`
## Workflow follow-up
- Архивировать изменение после удовлетворения требований ревью проекта.
- Проверить архивированный результат.