feat(photos): full EXIF metadata extraction, backfill and info panel
- backend: switch EXIF parser to dsoprea/go-exif/v3 (all recognised tags, numeric normalization); store in photos.exif jsonb (migration 000003); add storage.Get and cmd/backfill-exif to backfill existing photos from S3 originals - frontend: info panel renders all EXIF attributes with RU labels, enum translation and units (1/N, f/N, mm, EV); service tags hidden - viewer: remove make-cover action (cover managed from panel only), icon-only download - openspec: sync lightroom-workspace-ui artifacts (EXIF, cover-from-panel) and add plan for configurable info attributes/labels stored in user profile
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
- **Создание альбома.** Инлайн-форма заменяется иконочной кнопкой с хинтом, открывающей
|
||||
модалку ввода названия.
|
||||
- **Обложки.** `Album` получает `cover_thumb_url`; карточки и рейл показывают реальную
|
||||
миниатюру. Выбор обложки: пикер в правой панели и действие «сделать обложкой» в
|
||||
просмотре. Автообложка пишется только когда обложка ещё не задана; FK
|
||||
миниатюру. Выбор обложки: пикер в правой панели (действие «сделать обложкой» в
|
||||
просмотре не используется). Автообложка пишется только когда обложка ещё не задана; FK
|
||||
`albums.cover_photo_id -> photos(id) ON DELETE SET NULL` чинит висячие ссылки.
|
||||
- **Просмотр как маршрут.** `Lightbox`-оверлей заменяется маршрутом
|
||||
`/albums/:id/photos/:photoId` внутри шелла: крупное фото, filmstrip снизу, панель
|
||||
@@ -31,10 +31,20 @@
|
||||
ошибкой при превышении.
|
||||
- **Переименование фото.** `PATCH /photos/:id` меняет `original_filename`; инлайн-редактор
|
||||
в правой панели, доступный автору фото и owner/admin.
|
||||
- **Просмотр.** Полноэкранный режим (кнопка и хоткей `f`), зум колесом мыши, `Space` — 100%
|
||||
с панорамированием; удаление текущего фото с модальным подтверждением; возврат к обзору.
|
||||
- **Метаданные фото (EXIF).** При загрузке система извлекает все распознаваемые EXIF-атрибуты
|
||||
(камера, объектив, экспозиция, ISO, дата съёмки, GPS и др.) и хранит их в `photos.exif`;
|
||||
они возвращаются вместе с фото и показываются в разделе «Информация». Для ранее загруженных
|
||||
фото есть команда бэкфилла метаданных из оригиналов.
|
||||
- **Просмотр.** Полноэкранный режим (кнопка и `f`) с автоскрытием верхней/нижней панелей и
|
||||
стрелок у кромок; зум колесом к указателю (без прокрутки, максимум 200%), `Space`
|
||||
возвращает из любого зума во вписанный вид, в зуме догружается оригинал изображения;
|
||||
удаление текущего фото с модальным подтверждением; возврат к обзору.
|
||||
- **Разделы и панели.** Правая панель — сворачиваемые разделы (состояние сохраняется), с
|
||||
разделом «Информация» (EXIF/метаданные); левая и правая панели ресайзятся перетаскиванием.
|
||||
- **Настройки информации.** Раздел «Информация» получает кнопку-шестерёнку, открывающую
|
||||
модалку со списком EXIF-атрибутов: переключатели видимости и пользовательские подписи.
|
||||
Скрытые атрибуты сворачиваются под элементом «…» (клик раскрывает все). Настройки хранятся
|
||||
в профиле пользователя (server-side) и применяются ко всем фото.
|
||||
- **Счётчики.** В ответе альбома — число фото и участников.
|
||||
- **Темы и хром.** Существующие 4 темы сохраняются; `dark` — графит Lightroom и дефолт,
|
||||
`neutral` — тёплый графит; переключатель упорядочен тёмная → нейтральная → светлая →
|
||||
@@ -53,7 +63,8 @@
|
||||
|
||||
- `albums`: отображение обложки, счётчики фото/участников и явный выбор обложки.
|
||||
- `photos`: автообложка только при отсутствии выбора; переименование фото; лимит размера
|
||||
загрузки.
|
||||
загрузки; извлечение и хранение EXIF-метаданных.
|
||||
- `auth`: хранение пользовательских настроек отображения информации в профиле.
|
||||
|
||||
## Impact
|
||||
|
||||
@@ -63,14 +74,20 @@
|
||||
(presign → `CoverThumbURL`, обогащение списка); `internal/models` (`Album.CoverThumbURL`,
|
||||
`PhotosCount`, `MembersCount`); `internal/photos` (автообложка только при
|
||||
`cover_photo_id IS NULL`; `PATCH /photos/:id` для переименования; лимит загрузки 100 МБ с
|
||||
`413 file_too_large`; событие `photo.updated`).
|
||||
`413 file_too_large`; событие `photo.updated`; извлечение EXIF через
|
||||
`github.com/dsoprea/go-exif/v3` в `photos.exif`, миграция `000003_photo_exif`, команда
|
||||
`cmd/backfill-exif` и `storage.Get`); миграция `users.preferences`,
|
||||
`models.User.Preferences`, `internal/auth` (`Me` отдаёт настройки,
|
||||
`PATCH /auth/me/preferences` с валидацией).
|
||||
- **Frontend:** реструктуризация `+layout.svelte` в группы `(app)`/`(public)`, `AppShell`
|
||||
с ресайзом панелей и кнопкой полного экрана; компоненты рейла, контекстной панели со
|
||||
сворачиваемыми разделами и EXIF, модалки создания/пикера обложки/подтверждения,
|
||||
`Viewer` с полноэкранным режимом и зумом, общий стор альбомов, контрол плотности; новый
|
||||
маршрут `albums/[id]/photos/[photoId]`; новые значения токенов темы и стили скроллбаров;
|
||||
`types.ts` (+`cover_thumb_url`, счётчики, `photos_count`); новые иконки в реестре.
|
||||
- **Спеки:** `ui-workspace` (новая), `albums`, `photos` (дельты). `ui-iconography` не
|
||||
маршрут `albums/[id]/photos/[photoId]`; слот действий в `PanelSection`, модалка настроек
|
||||
атрибутов с пользовательскими подписями, стор настроек, фильтрация и «…» в панели;
|
||||
новые значения токенов темы и стили скроллбаров; `types.ts` (+`cover_thumb_url`, счётчики,
|
||||
`photos_count`, `preferences`); новые иконки в реестре.
|
||||
- **Спеки:** `ui-workspace` (новая), `albums`, `photos`, `auth` (дельты). `ui-iconography` не
|
||||
затрагивается — иконки по-прежнему наследуют цвет темы.
|
||||
- **Совместимость:** API-контракты сохраняются; добавляется поле ответа и один FK. Ломающих
|
||||
изменений API нет.
|
||||
|
||||
Reference in New Issue
Block a user