Skip to content

Photo-only delivery and a gallery page for photo share links - #128

Merged
MansiVisuals merged 1 commit into
MansiVisuals:devfrom
donutinit:feature/photo-only-delivery
Oct 6, 2026
Merged

MansiVisuals merged 1 commit into
MansiVisuals:devfrom
donutinit:feature/photo-only-delivery

Conversation

@donutinit

Copy link
Copy Markdown
Contributor

Closes #123

This is the PR for #123. I sometimes deliver photo sessions with ViTransfer and the share page always looked like a video review page, even with zero videos, and the client still had to click into the only album lol. So photo share links now open as a proper delivery gallery, something close to a Pixieset gallery, and there's a per-project switch that keeps the videos off the share link completely.

Summary

  • new per-project switch "Photo-Only Delivery" (Project.photoOnlyShare, default off) in the Client Share Page settings
  • with it on, recipients can't see, stream, download, comment on or approve any video through the share link. This is enforced in the API routes, the UI just follows
  • share links that deliver photos only (switch on, or photos and no ready videos) open a new gallery page instead of the overview

What changed

Photo-only switch (server)

With the switch on, for anyone who isn't an admin:

  • GET /api/share/[token] returns videos: [], videosByName: {} and photoOnlyShare: true
  • video-token, download-all-token, comments (read and write), approve, the /api/videos/[id]/* download, asset and client-asset routes, and TUS/S3 comment attachment uploads refuse the request
  • /api/content/[token] and /api/content/zip/[token] check the project too, so links minted before the switch was turned on stop working

Admins keep full access. Photos, photo downloads and reverse share uploads keep working.

Emails for photo-only projects:

  • recipients get no comment or reply emails. Anything already queued gets dropped by the digest worker or by the flush that runs when the schedule changes
  • recipients get no "project approved" email
  • "Send notification" always sends the general email, listing the album names instead of videos, and the dialog hides the per-video option

Gallery page

PhotoDeliveryGallery is what the share link shows when it has photos and no videos (or the switch is on):

  • full-screen cover using the album cover, with the title, description and a View Gallery button
  • sticky bar with the logo, title, photo count, a download button (open album or all albums as zip) and the language/theme toggles
  • the first album opens right away. More albums show up as tabs, and the open one stays in the URL as ?album=<id>, so a copied link opens the same album
  • masonry grid that keeps each photo's aspect ratio, using the existing thumbnails
  • with a mouse, each photo gets a download icon and a select circle, and selected photos download as a zip from a bar at the bottom. On touch screens those are hidden and downloads go through the lightbox and the top bar
  • albums with no finished photos are hidden
  • the admin share preview shows the same page

Shared bits

  • the album loading, paging and zip logic moved from SharePhotoSection into a useAlbumGallery hook. The old album view works the same and gets two fixes out of it: switching albums while a page was loading could leave the new album empty, and infinite scroll never prefetched because the observer watched the viewport while the grid scrolls inside its own container
  • PhotoLightbox is now a proper dialog (focus moves in and back out, Tab stays inside), swipes between photos on touch without triggering the browser's swipe back, and with paged albums the counter shows the album total and keeps going past the loaded page instead of wrapping to 1. It also has a gallery variant with a plain background for the new page
  • ThemeToggle and LanguageToggle got a ghost variant; the default look is unchanged
  • new strings in en, de and nl, and the wiki pages (Admin-Settings, Client-Guide, Features, Usage-Guide) are updated

Things you might want to know

  • projects that have photos but no ready videos open the gallery even with the switch off. Adding a video brings the normal overview back
  • the issue says to keep the overview when there are several albums. I went with tabs instead because that's how Pixieset does it and the client still picks what to open. Easy to change if you'd rather keep the overview there
  • the gallery doesn't show the tutorial, the grid/list toggle or the comments panel. The privacy banner and reverse share upload are still there
  • the admin share preview fetches the album list one extra time to decide which view to show
  • in S3 mode a presigned URL that was handed out before the switch keeps working until it expires, since a DB check can't revoke it
  • the PR targets dev because that's where recent PRs land, even though CONTRIBUTING mentions main

Validation

  • npx tsc --noEmit, npm run lint (no new warnings) and npm run build
  • ran it locally with next start and the worker (Postgres 18, Valkey, local storage) using a real photo session, plus generated albums with up to 230 photos and a project with 13 albums
  • API checks turning the switch off, on and off again on a project with an approved video: every video endpoint refuses, tokens minted before the switch stop streaming, photos and photo zips still work, the admin keeps access, and switching it off brings everything back
  • emails checked against a local SMTP sink: notify, immediate and hourly comment emails, the digest, the schedule change flush and approval, with the switch on and off
  • browser checks in headless Chromium at desktop size and at 390px with touch emulation: password, no-auth and guest links, fast album switching, pagination, keyboard and focus, dark mode, reduced motion, plus the old overview and the admin albums block for regressions
  • not tested: S3 mode, real iOS/Android devices, Safari and Firefox

@MansiVisuals

Copy link
Copy Markdown
Owner

Thank you for taking the time to create the PR for this feature.

I will look into it as soon as possible and try to merge it asap if/when possible.

I'll keep you posted.

Thanks again for contributing

MansiVisuals added a commit that referenced this pull request Oct 6, 2026
Contributor feature from #128, plus: the share-page guard centralised into
verifyProjectAccess, selection state in useAlbumGallery, one queue-drop
helper, and the gallery view derived from what the link carries rather than
from the switch.
@MansiVisuals
MansiVisuals merged commit 8958738 into MansiVisuals:dev Oct 6, 2026
@MansiVisuals

Copy link
Copy Markdown
Owner

Hi @donutinit

thanks a lot for this, its merged and ships in 1.4.0.

i did change a fair bit after merging to fit how vitransfer is put together, so i wanted to explain what and why.

the main one is the access check. you had the photo-only guard written out in each video route, which worked, but it meant every new video route has to remember to add it. i moved it into verifyProjectAccess as a requireVideoAccess option so its denied by default instead. the handful of routes that dont go through that helper kept their own check.

then the album view. you had the gallery for photo-only links and the existing full page album view for projects that also have videos, so the same photos looked different depending on whether the project happened to have a video in it. i made the gallery the album view everywhere, so clicking an album from the overview opens the same thing now with a back to overview button, and the old album view is gone.

i also changed what decides the view. it follows what the link actually carries rather than the switch, and it counts videos of any status, so a project with a video still transcoding doesnt flip from the overview to the gallery when encoding finishes.

the rest was styling, getting it onto our own tokens and components. the bar uses the same treatment as the video players bar, the buttons and hover states match the rest of the share page, and the accent colour from settings now comes through on the cover button, the open album and the photo selection.

the useAlbumGallery extraction was the best part of this and i didnt touch it, same for the two scroll fixes you found in there.

thanks again, really appreciate the effort. Let me know if anything looks off to you.

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.

2 participants