Files
ds-galo/openspec/changes/archive/2026-10-25-fix-edit-preview-handoff/proposal.md
T
iu 4d23e76ab5 chore(openspec): архивировать fix-edit-preview-handoff и обновить photos, realtime
- photos: признак незавершённого рендера правок, мгновенный показ сброса,
  бесшовная подмена предпросмотра
- realtime: события жизненного цикла рендера правок в photo.updated
2026-10-25 10:04:08 +03:00

5.9 KiB

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) его игнорируют.