Commit Graph
23 Commits
Author SHA1 Message Date
iu 2668d87347 fix(web): искажение цветов в предпросмотре правок
Таблицы тональных кривых в WASM-модуле лежали в статическом массиве, который
линковщик помещал в сегмент .data — такой сегмент в wasm доступен только для
чтения, поэтому запись в него не срабатывала, и модуль считал по мусорным
данным (отсюда «каша» вместо плавного градиента).

Теперь таблицы считает и передаёт JS: модуль не хранит состояния и только
применяет правки к пикселям. Дополнительно клиент сверяет модуль с эталонной
JS-реализацией на маленьком образце и, если они расходятся, доверяет JS.

Service worker больше не кэширует .wasm: старый модуль в кэше ломал
предпросмотр даже после обновления сборки.
2026-10-21 01:19:45 +03:00
iu f8ee93777d fix(web): зум в просмотре — контейнер прокрутки и центрирование
Прокручиваемый контейнер просмотра не имел min-w-0, поэтому в зуме он
раздувался до ширины картинки вместо того, чтобы прокручиваться: фото
нельзя было двигать влево-вправо. Та же правка применена к обёрткам просмотра.

Пробел теперь зумит к центру фото: 100% от оригинала с центрированием
изображения в просмотре.
2026-10-21 00:41:08 +03:00
iu b2a509fc38 fix(web): в зуме стрелки панорамируют фото
Стрелки влево/вправо переключают фото только без зума; в зуме они двигают
изображение, как и перетаскивание мышью.
2026-10-21 00:34:15 +03:00
iu 500ec10d7f fix(web): починить зум в просмотре
Механика зума переписана:

- Пробел зумит фото до 100% от оригинала (и обратно к вписанному виду).
- Колесо мыши зумит к курсору: точка под указателем остаётся на месте при
  любом изменении масштаба.
- Стрелки влево/вправо переключают фото и в зуме — панорамирование осталось
  за мышью.
- Масштаб и позиция считаются от размеров оригинала, а не от текущей рамки,
  поэтому зум не «уезжает» и картинка корректно центрируется.
2026-10-21 00:17:15 +03:00
iu 2adcb1374b fix(web): предпросмотр правок работает и без зума
Клиентский предпросмотр был включён только в зуме, поэтому в обычном виде
просмотра фото оставалось без правок. Теперь холст рисует ту часть картинки,
что попала во вьюпорт, в любом режиме, а под ним лежит неотредактированная
версия фото — так правки не применяются дважды.
2026-10-21 00:11:17 +03:00
iu 520886a11d feat(web): правки применяются на фронте, фильтры в WASM
Новый алгоритм редактирования: обработка идёт только на клиенте.

- Фильтры «Свет» считает WASM-модуль на Rust (frontend/wasm/light, 1.5 КБ):
  он строит тональные кривые и обрабатывает пиксели. При недоступности модуля
  используется JS-реализация с тем же результатом — расхождение проверяется
  тестом.
- Просмотр рисует видимую область фото с правками на canvas поверх
  исходной версии, поэтому изменения видны сразу, без ожидания рендера.
- Правки уходят на сервер не сразу: через десять секунд без изменений или при
  переключении фото. Сервер сохраняет параметры и готовит варианты сетки и
  полноразмерную версию в фоне, о готовности сообщает через SSE — клиент
  подтягивает готовую версию.
2026-10-21 00:06:46 +03:00
iu 4d2069d079 feat(photos): рендер только видимой области при зуме правок
Вместо полноразмерной отредактированной версии просмотр запрашивает у сервера
только видимую область кадра: координаты относительные, поэтому запрос не
зависит от размера оригинала. Рендер куска занимает около 0.15 с против 0.8 с
для всей картинки, а полноразмерная версия больше не готовится вовсе.

Зум больше не сбрасывается, когда приходит отрендеренная версия правок:
состояние просмотра сбрасывается только при смене самого фото.
2026-10-20 23:34:45 +03:00
iu 0548b1ab5e feat(web): вкладка «Редактирование» с инструментом «Свет»
В правой панели фото появилась вкладка «Редактирование» с инструментом «Свет»:
ползунки экспозиции, контраста, светов, теней, белых и чёрных и точечная кривая
с выбором канала. Правки сохраняются автоматически, переключатель «Сброс»
удаляет параметры правок и отредактированную версию фото.

Редактирование неразрушающее: параметры хранятся в метаданных фото, а
отредактированная версия рендерится в фоне отдельным объектом (edit, edit_thumb,
edit_medium, edit_preview) рядом с исходными вариантами. Оригинал не меняется,
скачивание отдаёт исходный файл. Сетка, просмотр и обложки альбомов показывают
отредактированную версию, когда она отрендерена.
2026-10-20 23:06:24 +03:00
iu 961dff15da feat(web): хоткей Ctrl+F для полноэкранного режима приложения
Кнопке «На весь экран» в верхней панели добавлен хоткей Ctrl+F. Хоткей `f`
полноэкранного просмотра больше не срабатывает на Ctrl+F: модификаторы
проверяются явно, поэтому сочетание свободно для кнопки каркаса.
2026-10-20 22:12:24 +03:00
iu 0a9e5274cf fix(web): лента миниатюр следует за текущим фото в просмотре
При переходе стрелками влево/вправо активная миниатюра нижней ленты уходила
за край и оставалась невидимой. Теперь лента прокручивается к текущему фото,
удерживая его плитку в поле зрения.
2026-10-20 22:06:20 +03:00
iu 35f84399bc feat(web): зум клавишами + и - в просмотре фото
В режиме просмотра фотографии (обычный и полноэкранный) клавиши + и - меняют
масштаб изображения на шаг, сохраняя точку в центре просмотра. Пока открыт
просмотр, эти клавиши больше не меняют размер миниатюр в сетке.
2026-10-20 22:01:41 +03:00
iu d38ede0201 feat(video): add video upload with remux/transcode playback
Add video as a media kind in photos: streaming upload with per-kind
limits, ffprobe metadata, poster frame reusing the image variant
pipeline, and a playback object (remux when web-compatible, else
h264/yuv420p/aac transcode). Video jobs run on a separate pool with a
long lease. Frontend gains a video viewer, grid badge/duration and
video upload.
2026-10-11 20:37:53 +03:00
iu a7867054a4 feat(ui): hover zoom on viewer thumbnail strip
- Thumbnails scale their image on pointer hover and keyboard focus
- Tile size and strip layout stay unchanged
2026-10-11 18:09:54 +03:00
iu fc4233cd57 feat(ui): 360 panorama viewer by pano360 tag
- Detect 'pano360' tag and open the photo in a spherical viewer
- Mini-WebGL equirect viewer (no deps): drag to look, wheel FOV, Space reset
- Load original as origin-clean bitmap; fall back to flat image without WebGL
- 360 indicator in viewer and badge on grid tiles
2026-10-11 17:41:28 +03:00
iu 61b45b2742 feat: context menus, unified photo panel, tags, album trash and counters
- backend: deleting an album moves its photos to the trash without losing files (photos.album_id nullable, FK ON DELETE SET NULL, migration 000006; dropped S3 prefix delete); restore accepts an album target (album_required when the album is gone); user-scoped tags (000007) with GET /tags, POST/DELETE /photos/:id/tags, tags included in photo responses; GET /trash/count
- frontend: right-click context menus for photos (grid + viewer) and albums (rail + overview); single shared PhotoPanel reused in viewer and gallery selection (not a copy); viewer download/delete moved to the panel 'Действия'; transparent compact viewer top bar; trash entry as last rail item with per-album photo counts and trash count; album rename/delete dialogs
- openspec: sync lightroom-workspace-ui artifacts (specs photos/ui-workspace, design #24-30, tasks 9.17-9.24)
2026-10-10 22:45:41 +03:00
iu 2d6a3fea1a feat: photo multiselect, move/copy, trash and compact chrome
- 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)
2026-10-10 22:13:17 +03:00
iu 642e3bcf8a fix(frontend): immediate viewer chrome and correct f fullscreen
- remove all hide timers in Viewer; top/bottom bars and arrows now show/hide immediately
- arrows reveal only within the viewer bounds (no longer stay visible when the pointer is over the left/right panels)
- f (and the viewer button) toggle the viewer's own fullscreen via nested fullscreen, so f works inside app-level fullscreen without turning it off
2026-10-10 21:26:46 +03:00
iu e1592549b2 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
2026-10-10 20:31:34 +03:00
iu d8da885020 feat(frontend): viewer zoom loads original and Space resets to fit
- in zoom, preload the full-resolution original and swap it in once loaded
  (preview is shown until then); revert to preview on zoom exit
- Space returns to the fitted view from any zoom level; from fit it goes to 100%
- derive zoom scale from the photo's true dimensions so 100% is accurate
2026-10-10 19:55:10 +03:00
iu d1e3aa85b4 feat(frontend): viewer fullscreen chrome and pointer-accurate zoom
- fullscreen: auto-hide top toolbar and filmstrip, revealed at top/bottom
  screen edge and hidden 1s after the cursor leaves
- arrows < >: edge-reveal in both normal and fullscreen; hide 300ms after
  leaving; hidden while zoomed
- zoom: wheel zooms only (no scroll, overscroll contained), anchored to the
  pointer, capped at 200%; Space toggles 100%/fit; pan via drag/scroll
2026-10-10 19:45:55 +03:00
iu 3886cc6511 feat(frontend): photo viewer fullscreen and zoom
- fullscreen toggle button + "f" hotkey (both layouts)
- wheel zoom anchored to cursor; Space toggles 100% (1:1)
- pan when zoomed via drag/scrollbars; reset zoom on photo change
- hotkeys ignored while typing in inputs
2026-10-10 19:15:43 +03:00
iu aa396bdb85 feat: photo rename and viewer delete with confirmation
Backend:
- add PATCH /api/photos/:id to rename original_filename (uploader/owner/admin)
- emit photo.updated SSE event

Frontend:
- inline filename editor in the right panel
- viewer: back button (arrow_back) on the left, delete on the right
- delete confirmed via a modal dialog; filmstrip updates after deletion
2026-10-10 18:50:16 +03:00
iu 304cfedb75 feat: lightroom-style workspace UI with album covers
Backend:
- expose cover thumbnail URL on album responses (LEFT JOIN + presign)
- auto-assign cover only when empty; FK cover_photo_id -> photos ON DELETE SET NULL
- add photos_count / members_count to album responses; cover repo test

Frontend:
- split layouts into (app) shell (resizable rail + contextual panel) and (public)
- album rail + create-album dialog; album panel with cover picker / make-cover
- photo viewer route with filmstrip, replacing lightbox; share reuses it
- grid density slider, toolbar + drag-and-drop upload, dark graphite default

OpenSpec: add lightroom-workspace-ui change (proposal, design, specs, tasks)
2026-10-10 18:15:13 +03:00