1.8 KiB
Gallery Tab
Nav id: gallery
Icon: ⊞
What it shows
A 2-column photo grid of images Quinn has shared with this specific client. Tapping a photo opens a full-screen lightbox.
Data flow
getGallery(token) — GET /vip/gallery?token=<token> — returns an array of VipGalleryItem.
Gallery item object
interface VipGalleryItem {
id: string
attachmentUrl: string // pre-signed or direct URL to the image
}
Display logic
Grid — display: grid, gridTemplateColumns: repeat(2, 1fr), gap: 4px. Square aspect ratio (1 / 1) with object-fit: cover. Images lazy-load via loading="lazy".
Lightbox — clicking any grid image sets lightbox state to that item. A fixed-position overlay at z-index: 100 renders the image at max-width: 100%, max-height: 90vh with object-fit: contain. Clicking the overlay or the ✕ button closes it; clicking the image itself stops propagation (so you can interact without closing).
Encryption
If the client has a content key (vip_content_key in sessionStorage), images may be served as encrypted blobs decrypted client-side. The current implementation uses direct attachmentUrl values — the API handles access control and optionally returns decryption metadata alongside the URL. This will evolve as the encryption pipeline matures.
Non-obvious details
- Gallery items are per-client — Quinn curates what each client sees via the admin panel. There is no global gallery that all clients share.
- Empty state text is "No shared photos yet." — not an error, just an honest empty state. Gallery being empty is normal for new invites.
- No pagination in the current implementation — all items load at once. This is acceptable for the expected volume (tens of photos per client, not thousands).