- photos: признак незавершённого рендера правок, мгновенный показ сброса, бесшовная подмена предпросмотра - realtime: события жизненного цикла рендера правок в photo.updated
70 lines
5.9 KiB
Markdown
70 lines
5.9 KiB
Markdown
# 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) его игнорируют.
|