- backend: soft delete + trash (photos.deleted_at, migration 000005), GET /trash, restore, permanent delete with storage-key refcount (S3 objects removed only when no other album references them); batch endpoints photo-batch/{delete,move,copy} - metadata only, copies clone rows sharing storage keys
- frontend: Ctrl/Shift multiselect; right-panel 'Действия' as icon text rows (Открыть (просмотр), Переместить, Копировать, Удалить); drag selected photos onto rail album -> TransferDialog; /trash route; trash entry as last item in the left rail; empty right panel hidden on overview
- frontend: compact top bars (app header and viewer), compact theme switcher
- openspec: sync lightroom-workspace-ui artifacts (photos/ui-workspace specs, design #20-24, tasks 9.11-9.17)
11 KiB
11 KiB
Proposal
Why
Сейчас интерфейс — это центрированный «маркетинговый» лейаут: список альбомов с
инлайн-формой создания, серая заглушка вместо обложек, отдельные страницы «Участники» и
«Настройки», лайтбокс-оверлей. Обложки в бэкенде уже есть (albums.cover_photo_id,
PATCH /albums/:id), но до UI не доходят. Пользователь хочет полноценный «рабочий стол»
в духе Adobe Lightroom: постоянный рейл альбомов, контекстная панель, плотная сетка,
режим просмотра как часть рабочего стола, обложки с явным выбором и единый тёмный
графитовый хром.
What Changes
- Рабочий стол (шелл). Группа
(app)с постоянным левым рейлом альбомов, топбаром и контекстной правой панелью. Публичные маршруты (/login,/invites/[token],/share/[token]) остаются вне шелла, но в тех же токенах. - Создание альбома. Инлайн-форма заменяется иконочной кнопкой с хинтом, открывающей модалку ввода названия.
- Обложки.
Albumполучаетcover_thumb_url; карточки и рейл показывают реальную миниатюру. Выбор обложки: пикер в правой панели (действие «сделать обложкой» в просмотре не используется). Автообложка пишется только когда обложка ещё не задана; FKalbums.cover_photo_id -> photos(id) ON DELETE SET NULLчинит висячие ссылки. - Просмотр как маршрут.
Lightbox-оверлей заменяется маршрутом/albums/:id/photos/:photoIdвнутри шелла: крупное фото, filmstrip снизу, панель метаданных/комментариев.share/[token]переиспользует тот же компонент. - Плотность сетки. Слайдер размера миниатюр в тулбаре (состояние в localStorage). Мультивыбор и массовые действия — вне объёма.
- Загрузка. Крупный dropzone заменяется кнопкой в тулбаре, полноэкранным drag-overlay и dropzone-намёком только в пустом альбоме. Лимит — 100 МБ с понятной ошибкой при превышении.
- Переименование фото.
PATCH /photos/:idменяетoriginal_filename; инлайн-редактор в правой панели, доступный автору фото и owner/admin. - Метаданные фото (EXIF). При загрузке система извлекает все распознаваемые EXIF-атрибуты
(камера, объектив, экспозиция, ISO, дата съёмки, GPS и др.) и хранит их в
photos.exif; они возвращаются вместе с фото и показываются в разделе «Информация». Для ранее загруженных фото есть команда бэкфилла метаданных из оригиналов. - Просмотр. Полноэкранный режим (кнопка и
f) с автоскрытием верхней/нижней панелей и стрелок у кромок; зум колесом к указателю (без прокрутки, максимум 200%),Spaceвозвращает из любого зума во вписанный вид, в зуме догружается оригинал изображения; удаление текущего фото с модальным подтверждением; возврат к обзору. - Разделы и панели. Правая панель — сворачиваемые разделы (состояние сохраняется), с разделом «Информация» (EXIF/метаданные); левая и правая панели ресайзятся перетаскиванием. Выбор фото в сетке показывается в панели (одиночный клик), двойной клик открывает просмотр.
- Настройки информации. Раздел «Информация» получает кнопку-шестерёнку, открывающую модалку со списком EXIF-атрибутов: галочки видимости (с действиями «отметить все»/«снять все»), пользовательские подписи и сброс. Скрытые атрибуты сворачиваются под элементом «…» (клик раскрывает все). Настройки хранятся в профиле пользователя (server-side), применяются ко всем фото, а при отсутствии настроек показывается базовый набор; «Сбросить» удаляет настройки из профиля.
- Мультивыбор и операции. Ctrl/Shift-выбор нескольких фото в сетке; в правой панели — раздел «Действия» с пунктами «Открыть (просмотр)», «Переместить», «Копировать», «Удалить»; перетаскивание выделенных фото на альбом в рейле открывает диалог перенос/копирование. Перенос и копирование меняют только метаданные (объекты S3 не трогаются). Любое удаление помещает фото в корзину; объекты S3 удаляются лишь когда на них нет ссылок в других альбомах. Корзина — последний элемент списка альбомов в левом рейле (иконка корзины); на обзоре убрана пустая правая панель.
- Счётчики. В ответе альбома — число фото и участников.
- Темы и хром. Существующие 4 темы сохраняются;
dark— графит Lightroom и дефолт,neutral— тёплый графит; переключатель упорядочен тёмная → нейтральная → светлая → системная; добавляются токены--chrome/--canvas; скроллбары стилизованы в тон темы. Верхняя панель приложения и верхняя панель режима просмотра — компактные (минимум высоты). - Адаптив. На узких экранах рейл становится off-canvas drawer, правая панель — bottom-sheet, filmstrip — горизонтальным скроллом.
Capabilities
New Capabilities
ui-workspace: рабочий стол приложения — шелл, рейл альбомов, контекстная панель, режим просмотра как маршрут, адаптивное поведение и тёмный хром.
Modified Capabilities
albums: отображение обложки, счётчики фото/участников и явный выбор обложки.photos: автообложка только при отсутствии выбора; переименование фото; лимит размера загрузки; извлечение и хранение EXIF-метаданных; перенос/копирование и корзина.auth: хранение пользовательских настроек отображения информации в профиле.
Impact
- Backend: миграция FK
albums.cover_photo_id -> photos(id) ON DELETE SET NULL;internal/albums/store.go(LEFT JOINphotos→cover_thumb_keyи счётчикиphotos_count/members_countвListForUser/GetByID);internal/albums/service.go(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; извлечение 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]; слот действий вPanelSection, модалка настроек атрибутов с пользовательскими подписями, стор настроек, фильтрация и «…» в панели; новые значения токенов темы и стили скроллбаров;types.ts(+cover_thumb_url, счётчики,photos_count,preferences); новые иконки в реестре. - Спеки:
ui-workspace(новая),albums,photos,auth(дельты).ui-iconographyне затрагивается — иконки по-прежнему наследуют цвет темы. - Совместимость: API-контракты сохраняются; добавляется поле ответа и один FK. Ломающих изменений API нет.