49 lines
1.8 KiB
Markdown
49 lines
1.8 KiB
Markdown
# 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
|
|
|
|
```typescript
|
|
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).
|