feat(frontend): select photo in album grid and show info in panel

- single click selects a photo (ring + aria-pressed) and shows its info in the right panel without navigating; double click opens the viewer
- shared 'selection' store; panel uses the route photo in viewer mode and the selected photo in album mode; selection resets on album change
- openspec: sync lightroom-workspace-ui (grid-selection requirement, viewer chrome wording without timers, nested f fullscreen, tasks 9.9/9.10)
This commit is contained in:
iu
2026-10-10 21:33:59 +03:00
parent 642e3bcf8a
commit 78996bc053
8 changed files with 114 additions and 33 deletions
@@ -104,10 +104,13 @@ filmstrip, панель метаданных/комментариев, тулб
### 13. Просмотр: полный экран и зум
Полный экран — `requestFullscreen` на корне `Viewer` (кнопка + `f`), состояние — по
`fullscreenchange`. В полноэкранном режиме верхняя/нижняя панели и стрелки соседних фото
скрыты и всплывают у соответствующих кромок (панели — по касанию края, скрытие ~1 с после
ухода; стрелки — при курсоре в 1/6 левой/правой области, скрытие ~300 мс; в зуме стрелки
скрыты полностью). Зум — состояние `zoomed`/`scale` с масштабом от истинных размеров фото:
`fullscreenchange`. `f`/кнопка переключают именно полноэкранный режим вьюера: если активен
полноэкранный режим приложения, `f` входит в просмотр фото вложенным режимом и не выключает
режим приложения. В полноэкранном режиме верхняя/нижняя панели и стрелки соседних фото
всплывают у соответствующих кромок без таймеров — показываются и скрываются сразу по позиции
курсора (панели — по касанию края; стрелки — при курсоре в 1/6 левой/правой области, только
внутри границ вьюера, поэтому при уходе в боковые панели они скрыты; в зуме стрелки скрыты
полностью). Зум — состояние `zoomed`/`scale` с масштабом от истинных размеров фото:
колесо зумит с привязкой к указателю (без прокрутки, `overscroll-contain`), предел — 200%;
`Space` возвращает из любого зума во вписанный вид, а из вписанного — в 100%; вход в зум
догружает оригинал и подменяет его по факту загрузки (до этого — превью); панорамирование —
@@ -162,6 +165,15 @@ EXIF извлекается при загрузке и хранится в `phot
`exif`/`taken_at`/координаты. Альтернатива — фиксированный набор полей — отклонена:
пользователю нужны все атрибуты.
### 19. Выбор фото в сетке через общий стор
Выбор фото в сетке и контекстная панель живут в разных местах дерева (страница маршрута и слот
`AppShell`), поэтому выбранное фото хранится в общем сторе `selection` (`albumId` + `photo`).
Одиночный клик в `PhotoGrid` записывает выбор (рамка `ring` + `aria-pressed`), и панель
показывает сведения о выбранном фото; двойной клик открывает маршрут просмотра. Панель
использует `panelPhoto = photoId ? routePhoto : selectedPhoto`, поэтому в просмотре приоритет у
маршрута, а в альбоме — у выбора; выбор сбрасывается при смене альбома. Альтернатива — хранить
выбор в URL (query) — избыточно для локального выделения.
## Risks / Trade-offs
- [Много альбомов → много presign в списке] → presign это локальная крипто-операция без сети;