docs(openspec): изменение fix-edit-preview-handoff

- proposal/design/tasks и delta-спеки photos, realtime
- серверный признак edit_pending, бесшовная подмена предпросмотра, мгновенный сброс
This commit is contained in:
iu
2026-10-25 10:02:04 +03:00
parent 4d5cf3c1cb
commit 1c29f5d961
6 changed files with 374 additions and 0 deletions
@@ -0,0 +1,69 @@
# Proposal
## Why
Клиент узнаёт о готовности серверного рендера правок только по появлению
`edit_url`/`edit_preview_url` в объекте фото, а признака «рендер сохранённых правок
ещё идёт» в API нет. Из-за этого в просмотрщике:
- после отложенного сохранения (дебаунс 10 с) при появлении полного рендера
клиентский предпросмотр выключается раньше, чем новое изображение загружено, и
в зуме на время загрузки виден оригинал (мигание «оригинал → правка»);
- повторная правка, у которой уже есть предыдущий рендер, после сохранения
показывает старую отрендеренную версию, пока не завершится новый рендер;
- сброс, сделанный возвратом контролов в значения по умолчанию, не виден до
срабатывания дебаунса: локальные параметры уже пусты, предпросмотр выключен, и
просмотрщик показывает старую серверную версию — «сброс срабатывает через 10 с».
## What Changes
- Фото получает аддитивный признак незавершённого рендера правок — булево поле
`edit_pending` в ответах API и в событиях `photo.updated`: `true`, пока в
`edit_jobs` есть задание на рендер; `false`, когда рендера нет или он завершён.
- Клиент перестаёт угадывать готовность по наличию URL и опирается на признак:
пока есть несохранённые локальные правки или серверный рендер не завершён,
просмотрщик показывает клиентский предпросмотр поверх исходной версии.
- Замена предпросмотра серверной версией выполняется только после загрузки и
декодирования нового изображения — без промежуточного показа оригинала или
предыдущей отрендеренной версии.
- Сброс правок (кнопкой и возвратом контролов в значения по умолчанию) виден в
просмотрщике сразу, не дожидаясь отложенного сохранения.
- Viewer перестаёт предпочитать устаревшую локальную копию фото: URL для показа
берутся из актуального объекта, обновляемого SSE-событиями.
- Индикатор «Рендерим правки на сервере…» в панели редактора опирается на
`edit_pending`, а не на отсутствие URL.
- Без изменений: отложенное сохранение (10 с), неразрушающий рендер, роли
объектов, формат `edit_params`, схема БД, Android-клиент (поле аддитивное,
отсутствие трактуется как `false`).
## Capabilities
### New Capabilities
Нет — изменение уточняет существующие способности.
### Modified Capabilities
- `photos`: новый признак незавершённого рендера правок; уточняются «Живой
предпросмотр цветовых правок», «Живой предпросмотр эффектов» (бесшовная
подмена) и добавляется требование о мгновенном показе сброса.
- `realtime`: `photo.updated` отражает жизненный цикл рендера правок — сохранение
(`edit_pending=true`), готовность (`edit_pending=false` + URL отредактированных
вариантов), сброс (без URL отредактированных вариантов).
## Impact
- `backend/internal/models/models.go` — поле `EditPending` в `Photo`.
- `backend/internal/photos/store.go`, `sqlite_store.go` — `EXISTS` по `edit_jobs`
в общем списке колонок; сканирование поля. Миграции не нужны: таблица уже есть.
- `backend/internal/photos/edit_service.go`, `worker.go`, `handlers.go` — признак
попадает в ответы сохранения/сброса и в события (через общие запросы фото).
- `frontend/src/lib/types.ts` — поле в типе `Photo`.
- `frontend/src/lib/components/Viewer.svelte` — выбор источника изображения по
состоянию (локальные правки / `edit_pending` / загруженность нового кадра),
предзагрузка и декодирование, единый актуальный источник URL.
- `frontend/src/lib/components/PhotoEditPanel.svelte` — статус рендера.
- Новый чистый модуль выбора источника предпросмотра + vitest.
- Тесты: контрактные (репозитории, SQLite и Postgres), e2e рендера правок,
frontend-модульные тесты, проверка `svelte-check`.
- API: аддитивное поле `edit_pending`; старые клиенты (Android) его игнорируют.