- synced delta specs into main specs: albums (+3 reqs, MODIFIED deleting album -> photos to trash), auth (+1), photos (+8), and created new ui-workspace spec (29 reqs) - moved the change to openspec/changes/archive/2026-10-10-lightroom-workspace-ui/
13 KiB
13 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с валидацией); миграции000005_photo_trash(мягкое удаление),000006_photo_album_nullable(FKphotos.album_id→ON DELETE SET NULL, удаление альбома в корзину),000007_photo_tags(метки);GET /trash/GET /trash/count,POST /photos/:id/restore(calbum_id),DELETE /photos/:id/permanent,POST /photo-batch/{delete,move,copy},GET /tags,POST/DELETE /photos/:id/tags. - Frontend: реструктуризация
+layout.svelteв группы(app)/(public),AppShellс ресайзом панелей и кнопкой полного экрана; компоненты рейла, контекстной панели со сворачиваемыми разделами и EXIF, модалки создания/пикера обложки/подтверждения,Viewerс полноэкранным режимом и зумом, общий стор альбомов, контрол плотности; новый маршрутalbums/[id]/photos/[photoId]; слот действий вPanelSection, модалка настроек атрибутов с пользовательскими подписями, стор настроек, фильтрация и «…» в панели; новые значения токенов темы и стили скроллбаров;types.ts(+cover_thumb_url, счётчики,photos_count,preferences,tags); общие компонентыPhotoPanel,ContextMenu,TransferDialog,AlbumActionsDialogs; маршрут/trash; сторыselection,transfer,contextMenu,albumActions,trash,viewerActions; новые иконки в реестре. - Спеки:
ui-workspace(новая),albums,photos,auth(дельты).ui-iconographyне затрагивается — иконки по-прежнему наследуют цвет темы. - Совместимость: API-контракты сохраняются; добавляется поле ответа и один FK. Ломающих изменений API нет.