Skip to content

Add cursor-based pagination to the media lightbox (fix 12-photo ceiling) - #42

Open
TomProkop wants to merge 1 commit into
mainfrom
users/tomas.prokop/lightbox-pagination
Open

Add cursor-based pagination to the media lightbox (fix 12-photo ceiling)#42
TomProkop wants to merge 1 commit into
mainfrom
users/tomas.prokop/lightbox-pagination

Conversation

@TomProkop

Copy link
Copy Markdown
Member

Problem

After PR #37 (server-side display resize + 12-post grid cap + capturedAt sort), the live photo grid and map-side photo tile both trapped lightbox navigation to only the posts they'd already loaded — 12 for the grid preview, or (before that) whatever useMediaPosts()'s first API page happened to contain. With hundreds of trip photos, browsing "next" would silently wrap back to the start well before reaching the archive's end.

Raising the fetch limit was rejected as a real fix since it just moves the ceiling (e.g. to 500) instead of removing it.

Fix: on-demand cursor pagination

  • api/src/functions/media.ts: new optional ?before=<ISO capturedAt> query param. Filters the already-sorted (by capturedAt desc) result to strictly-older-than-before. Response shape changes from a bare array to { posts, hasMore } — the only frontend caller of this endpoint (useMediaPosts.ts) is updated accordingly; mediaMine.ts/mediaDisplay.ts are separate endpoints, unaffected.
  • src/hooks/useMediaPosts.ts: unwraps the new response shape internally; external return type (MediaPost[]) is unchanged, so the grid, map pins, and day-stats consumers of this hook need no changes.
  • src/components/MediaLightbox.tsx: new opt-in enablePagination prop (default off). When enabled, goNext() fetches the next page from /api/media?before=... once the currently-loaded posts are exhausted, appends, and advances — only wrapping to the start once the backend reports hasMore: false. The bottom counter shows just the position (no "/ total") while more could still be loaded, since the real total isn't known yet.
  • src/components/PhotoStream.tsx / src/components/RouteMap/PhotoStreamTile.tsx: pass the full (unsliced) useMediaPosts() result + enablePagination to the lightbox. Grid/tile previews keep their existing small caps (12 / 6) — only the lightbox's browsing scope changes.
  • MediaMarkers.tsx is untouched — its cluster/nearby-radius lightbox opens are intentionally scoped subsets, not "browse the whole archive," so pagination doesn't apply there.

Verification

  • npx tsc -b (frontend) — clean
  • cd api && npm run build — clean
  • npx oxlint on changed files — no new warnings (one pre-existing exhaustive-deps warning, confirmed present on main before this change too)

Fixes a hard ceiling on browsing past the grid's preview/fetch page:
the lightbox previously could only ever navigate within whichever
posts useMediaPosts() had already fetched (first page, capped at
MAX_LIMIT), so a trip archive with hundreds of photos would silently
wrap back to the start once you scrolled past that.

- api/media.ts: support ?before=<ISO capturedAt> cursor, filtered after
  the existing full-partition sort; response shape changes from a bare
  array to { posts, hasMore }.
- useMediaPosts.ts: unwrap the new response shape; external hook
  signature (MediaPost[]) unchanged, so grid/map/day-stats consumers
  need no changes.
- MediaLightbox.tsx: new opt-in enablePagination prop. When on,
  goNext() fetches the next page on demand once the loaded set is
  exhausted (appends, then advances) instead of wrapping, until the
  backend reports hasMore: false. Counter omits "/ total" while more
  could still be loaded. Off by default, so MediaMarkers.tsx's
  intentionally-scoped cluster/nearby-radius lightboxes keep wrapping
  within just their subset.
- PhotoStream.tsx / PhotoStreamTile.tsx: pass the full (unsliced)
  posts list + enablePagination to the lightbox; grid/tile previews
  keep their existing small caps (12 / 6).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant