fix(photos): убрать мигание предпросмотра и задержку сброса правок

- фото и photo.updated несут edit_pending: рендер сохранённых правок ещё идёт
- клиент держит предпросмотр, пока серверная версия не загружена и не
  декодирована, поэтому оригинал не мелькает при подмене
- сброс возвратом контролов в значения по умолчанию виден сразу, не через 10 с
- Viewer берёт URL из актуального объекта (SSE), fresh остаётся фолбэком
- попутно исправлен порядок чтения tags и album_title в ListTrash
This commit is contained in:
iu
2026-10-25 10:02:04 +03:00
parent 1c29f5d961
commit 2b8d329a3e
10 changed files with 495 additions and 89 deletions
+4 -3
View File
@@ -41,7 +41,8 @@ const sqlitePhotoColumns = `p.id, COALESCE(p.album_id, ''), p.uploader_id,
COALESCE((SELECT json_group_array(json_object('id', t.id, 'name', t.name))
FROM (SELECT t.id, t.name FROM photo_tags pt JOIN tags t ON t.id = pt.tag_id
WHERE pt.photo_id = p.id AND t.user_id = $2
ORDER BY lower(t.name)) t), '[]')`
ORDER BY lower(t.name)) t), '[]'),
EXISTS(SELECT 1 FROM edit_jobs ej WHERE ej.photo_id = p.id)`
const sqlitePhotoJoins = `
LEFT JOIN photo_objects po_o ON po_o.photo_id = p.id AND po_o.role = 'original'
@@ -76,7 +77,7 @@ func scanSQLitePhoto(scan func(...any) error) (*models.Photo, error) {
&p.Kind, &p.DurationMS,
&takenAt, &lat, &long, &p.Caption, &createdAt,
&p.Uploader.ID, &p.Uploader.Name, &p.Uploader.AvatarURL,
&p.LikesCount, &p.CommentsCount, &liked, &exifText, &deletedAt, &editText, &tagsText); err != nil {
&p.LikesCount, &p.CommentsCount, &liked, &exifText, &deletedAt, &editText, &tagsText, &p.EditPending); err != nil {
return nil, err
}
p.TakenAt = sqliteutil.ParseNullTime(takenAt)
@@ -311,7 +312,7 @@ func (s *SQLiteStore) ListTrash(ctx context.Context, userID string) ([]models.Ph
&p.Kind, &p.DurationMS,
&takenAt, &lat, &long, &p.Caption, &createdAt,
&p.Uploader.ID, &p.Uploader.Name, &p.Uploader.AvatarURL,
&p.LikesCount, &p.CommentsCount, &liked, &exifText, &deletedAt, &editText, &albumTitle, &tagsText); err != nil {
&p.LikesCount, &p.CommentsCount, &liked, &exifText, &deletedAt, &editText, &tagsText, &p.EditPending, &albumTitle); err != nil {
return nil, err
}
p.TakenAt = sqliteutil.ParseNullTime(takenAt)
+5 -4
View File
@@ -47,7 +47,8 @@ const photoColumns = `p.id, COALESCE(p.album_id, ''), p.uploader_id,
COALESCE(p.edit_params, '{}'::jsonb)::text,
COALESCE((SELECT json_agg(json_build_object('id', t.id, 'name', t.name) ORDER BY lower(t.name))
FROM photo_tags pt JOIN tags t ON t.id = pt.tag_id
WHERE pt.photo_id = p.id AND t.user_id = $2), '[]')::text`
WHERE pt.photo_id = p.id AND t.user_id = $2), '[]')::text,
EXISTS(SELECT 1 FROM edit_jobs ej WHERE ej.photo_id = p.id)`
const photoJoins = `
LEFT JOIN photo_objects po_o ON po_o.photo_id = p.id AND po_o.role = 'original'
@@ -79,7 +80,7 @@ func scanPhoto(row pgx.Row) (*models.Photo, error) {
&p.Kind, &p.DurationMS,
&p.TakenAt, &p.Latitude, &p.Longitude, &p.Caption, &p.CreatedAt,
&p.Uploader.ID, &p.Uploader.Name, &p.Uploader.AvatarURL,
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &tagsText)
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &tagsText, &p.EditPending)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
@@ -228,7 +229,7 @@ func (s *Store) List(ctx context.Context, in ListParams) ([]models.Photo, error)
&p.Kind, &p.DurationMS,
&p.TakenAt, &p.Latitude, &p.Longitude, &p.Caption, &p.CreatedAt,
&p.Uploader.ID, &p.Uploader.Name, &p.Uploader.AvatarURL,
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &tagsText); err != nil {
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &tagsText, &p.EditPending); err != nil {
return nil, err
}
setExif(&p, exifText)
@@ -348,7 +349,7 @@ func (s *Store) ListTrash(ctx context.Context, userID string) ([]models.Photo, e
&p.Kind, &p.DurationMS,
&p.TakenAt, &p.Latitude, &p.Longitude, &p.Caption, &p.CreatedAt,
&p.Uploader.ID, &p.Uploader.Name, &p.Uploader.AvatarURL,
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &p.AlbumTitle, &tagsText); err != nil {
&p.LikesCount, &p.CommentsCount, &p.LikedByMe, &exifText, &p.DeletedAt, &editText, &tagsText, &p.EditPending, &p.AlbumTitle); err != nil {
return nil, err
}
setExif(&p, exifText)