Commit Graph

7 Commits

Author SHA1 Message Date
0f65bfb94a feat(web): native favorites, lightbox zoom, EXIF jump links + perf fix
- Favorites use PhotoPrism's own like/unlike endpoint (not a mule-only
  mark) so they sync to third-party gallery apps, with heart controls
  in the tile, sidebar, and an `f` shortcut.
- Lightbox: wheel-zoom around cursor, double-click to 2.5x, drag-to-pan,
  auto-upgrades to the fit_2048 tile past 1.25x zoom.
- Sidebar: copy-EXIF button, clickable Camera/Lens values that jump to
  a filtered timeline (camera:/lens: DSL), matching the existing
  Country link.
- Fix filtersToQ() quoting the entire search string whenever it
  contained a colon, which silently turned any raw DSL operator
  (camera:, taken:2024, etc.) into a literal phrase search — discovered
  while verifying the new jump-links against production.
- Disable TanStack Query's refetchOnWindowFocus: the indexer WebSocket
  already invalidates photo queries on real changes, so the focus
  refetch was just a redundant full-timeline re-render on tab-switch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 21:56:49 +02:00
73c36b4817 revert evictFromCache, add back delay + marks invalidation
Remove evictFromCache entirely - the cache-manipulation approach was
brittle and broke both archive (photos not removed) and tags
(colors/ratings showing empty). Replace with: 200ms delay before
invalidation to let PhotoPrism's indexer process the change, plus
invalidateQueries(['marks']) so tag caches (colors, ratings, notes)
refresh alongside the photo timeline.
2026-06-07 22:31:39 +02:00
1df16a6142 perf: evict archived/deleted photos from cache immediately
Remove archived/restored/deleted/approved UIDs from all cached photo-list
pages right after the API confirms, so the grid updates on the same tick
instead of waiting for a network round-trip. Also removes the 400ms
doneBulk animation delay (now unnecessary since tiles vanish instantly).
2026-06-07 21:53:16 +02:00
5da1022ed1 feat: loading toasts for all photo actions
Add loading→success/error toast transition to every bulk operation
(archive, restore, delete, approve, add-to-heap, metadata patch).
Also wires gridKeyNav + CauseGroupCard into the bulkAction store so
keyboard-triggered actions show the same per-tile pending/done/error
feedback as BulkActionBar buttons.
2026-06-07 21:40:18 +02:00
c134afe023 web(review): confidence-aware date guesser with combined filename + path signals
Refactor suggestDateFromPath to combine multiple signals instead of
trying patterns in priority order:

- Filename Y-M-D corroborated by path Y-M/Y-M-D → HIGH (filename-
  agrees-path). Fixes the case where a Samsung-style 20240226_xxx.jpg
  under 2024/02/ was returning the path-only 2024-02-01.
- Filename Y-M-D with no path signal → HIGH (filename-only).
- 10/13-digit Unix epoch in basename → HIGH (unix-timestamp) —
  covers WeChat (mmexport...) and FB saves.
- Path Y-M-D → HIGH (path-ymd).
- Path Y-M only → MEDIUM (path-ym-default-day, synthesised day=01).
  Sidebar row labels these "(estimated day)" so the user knows.

Filename parser now accepts `.` and space separators (covers macOS
screenshots, manual 2024.02.26 renames). Path parser accepts `.` too.
OriginalName participates as a secondary filename signal when present
and different from the on-disk basename.

Patterns we explicitly DO NOT parse, to avoid silent date flips:
DD-MM-YYYY / MM-DD-YYYY, 2-digit years, bare camera sequence numbers.

Add photoNameAndDir(p) helper next to primaryFile so RightSidebar,
BulkActionBar, photoActions, and gridKeyNav all derive {fileName,
path} the same way — fixes the bug where photo.FileName was
undefined on the single-photo detail endpoint and the basename branch
was being skipped entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:04:48 +02:00
97f51a05c4 web(review): scope date suggestion to EXIF Stripped tab + 'a' shortcut
- Gate the sidebar's "Suggested from path" row on /review?tab=stripped_exif
  instead of a per-photo TakenSrc heuristic — PhotoPrism stores a guessed
  TakenAt for stripped-EXIF photos too, so the heuristic was hiding the
  row even when a path-derived date was available.
- Same gate on the BulkActionBar's "Accept date & Keep" button.
- Extract acceptDateAndKeep() + cachedPhoto() into photoActions so the
  bar button and a new bare-'a' shortcut in gridKeyNav share one path.
- Show an 'A' kbd hint on the bar button.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:31:04 +02:00
Claudio
8ac406ac1f Review view: reuse timeline action surface, simpler card UX
The /review cards now share the timeline's PhotoGrid, gridKeyNav,
BulkActionBar, and global selection store instead of carrying parallel
implementations. The card is reduced to a header (title + count +
Dismiss / Archive all), an advisory caption, and a PhotoGrid; keyboard
nav, hover affordances, multi-select, and bulk verbs come from the
shared machinery.

- New web/src/lib/services/photoActions.ts holds the canonical
  dismissPhotos / archivePhotos helpers (toast wording, focus advance,
  undo push, ['photos'] + ['review-groups'] cache invalidation).
  BulkActionBar.onApprove / onArchive and gridKeyNav.approveCullTargets
  / toggleArchive('archive') route through it. CauseGroupCard's
  Dismiss / Archive-all buttons call the same helpers - one code path
  from any surface.

- Approve verb renamed to "Dismiss" across BulkActionBar, gridKeyNav
  toasts ("Kept N" -> "Dismissed N"), and the new review card. The
  BulkActionBar Clear/Dismiss clear button is just "Clear" now so the
  verb only means the action.

- /review sets filters.section='review' on mount and restores on
  unmount, which is what swings the shared action surface into review
  semantics; an effect clears the selection on tab change so a
  previously-selected photo from another cause can't be hit by a new
  tab's bulk verb.

- The route mounts BulkActionBar at the bottom and swaps the right
  aside to BulkMetadataSidebar when selection.ids.size >= 2 - same as
  the timeline; gives the user a one-shot "apply this Date / Caption /
  Keyword to all selected" affordance for EXIF-stripped batches.

- CauseGroupCard drops its bespoke keyboard handler, ResizeObserver,
  focusedIdx state, per-tile hover Approve/Archive buttons, confirm()
  dialogs, and toast.loading worker loop. The unused CauseBadges
  component is removed.
2026-05-18 18:50:23 +00:00