Mobile: real swipe physics, pinch zoom, touch-first lightbox
ci / docker (push) Successful in 17s

- swipe sideways to browse (track follows the finger, FLIP settle),
  flick up/down to vote Tinder-style with ghost fly-off and the next
  photo zooming in behind; votes and navigation commit synchronously on
  release — animations are pure decoration, so closing or keypresses
  mid-animation can't drop or duplicate an action
- two fingers pinch-zoom the photo (springs back, never votes)
- voting the last photo fades the modal out over the gallery
- gesture engine extracted to useSwipe: per-move motion via direct DOM
  writes (no React render per touchmove), named threshold constants
- touch devices: selection checkmarks always visible, nav arrows yield
  to swiping, finger-sized vote/rating targets, safe-area padding
This commit is contained in:
2026-07-17 17:18:51 +02:00
parent 037b68fc9d
commit 7167af8984
7 changed files with 496 additions and 24 deletions
+12 -8
View File
@@ -57,7 +57,10 @@ The lightbox — accept/reject, star rating, tags, and keyboard-driven culling
- **Frontend**: React + Vite SPA — justified gallery, lightbox with
accept/reject thumbs, rating stars and tag chips, keyboard-driven culling
(`P`/`X`/`U`, `1``5`, `?` shows all shortcuts), drag-and-drop multi-file
upload with progress.
upload with progress. Touch-first on mobile: swipe sideways to browse,
flick a photo up/down to accept/reject (real physics — votes commit
instantly, the animation is decoration), pinch to zoom, always-visible
selection checkmarks. Voting the last photo fades back to the gallery.
## Local development
@@ -105,20 +108,20 @@ All configuration is via environment variables:
## Deploying to Kubernetes
Build and push the image (single image contains `server`, `worker`, and the
built frontend):
The prebuilt image is at `git.draic.info/nils/photos` (single image contains
`server`, `worker`, and the built frontend). To build your own instead:
```sh
docker build -t ghcr.io/YOU/photos:0.1.0 .
docker push ghcr.io/YOU/photos:0.1.0
docker build -t registry.example.com/you/photos:0.4.0 .
docker push registry.example.com/you/photos:0.4.0
```
Install the chart, pointing it at your existing Postgres and S3:
```sh
helm install photos deploy/chart \
--set image.repository=ghcr.io/YOU/photos \
--set image.tag=0.1.0 \
--set image.repository=git.draic.info/nils/photos \
--set image.tag=0.4.0 \
--set publicUrl=https://photos.example.com \
--set ingress.host=photos.example.com \
--set config.oidcIssuer=https://auth.example.com \
@@ -159,7 +162,8 @@ Notes:
stored **per link**, so create one link per client to keep feedback
separate. The album view shows all feedback grouped by link label, and
clients can filter their gallery by verdict (e.g. review only what's still
undecided, or select-all + download the accepted set).
undecided, or select-all + download the accepted set). Culling works with
keyboard (`P`/`X` auto-advance) on desktop and swipe gestures on mobile.
- Clients (and you) can multi-select photos and download them — or the whole
album — as a ZIP. Archives are streamed (each file spools briefly through a
temp file for its checksum, then pipelines while the next one prefetches),