6 Commits

Author SHA1 Message Date
5105b42c46 Prevent blob eviction: store as ArrayBuffer + request persistence
iOS Safari evicts Blob file-backed data from IndexedDB under memory
pressure, causing upload POSTs to throw 'Load failed' without ever
reaching the server. Two-pronged fix:

1. Store photos as ArrayBuffer (inline bytes) instead of Blob (file
   reference) in IndexedDB — ArrayBuffers are not subject to eviction
2. Request navigator.storage.persist() to signal the browser not to
   evict our storage under pressure

Also adds Storage.getBlob() helper for converting stored ArrayBuffer
back to Blob at upload/display time, with backward compat for any
existing Blob-stored photos.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 16:01:07 -06:00
32801852cb Add milliseconds to photo filenames to prevent overwrites
Filenames now include milliseconds (e.g. kamaji_20260207_143022347.jpg)
so rapid consecutive captures don't produce identical names and
overwrite each other on Nextcloud.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 05:17:52 -06:00
c4a6239f46 Improve JPEG output quality
- Live camera: 0.92 -> 0.97 quality
- Library upload: 0.92 -> 0.97 starting quality
- Size limit: 10MB -> 20MB before compression kicks in
- Gentler quality steps: drops by 0.03 instead of 0.1
- Higher quality floor: 0.50 instead of 0.30
- Gentler downscaling: 0.85x instead of 0.8x per step

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 05:03:23 -06:00
0f1a4f82a9 Add upload from photo library button on capture screen
Adds an "Upload from Library" button below the camera button
that opens the device photo picker (no capture attribute) with
multi-select support. Selected photos are converted to JPEG and
queued for upload, with a progress counter during processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 05:00:40 -06:00
e37cf878d0 Replace file-input capture with live camera viewfinder
The previous approach used setTimeout to re-trigger the file input
after each capture, which iOS Safari blocks because it loses the
user gesture context.

Now uses getUserMedia for a fullscreen camera viewfinder that stays
open between shots. Shutter button captures frames from the video
stream, saves to IndexedDB, and the camera remains open until the
user taps close. Includes flash feedback, session counter, and
camera flip. Falls back to single-shot file input if getUserMedia
is unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 04:56:16 -06:00
cad4118f72 Add NextSnap PWA with photo gallery viewer and continuous capture
Offline-first photo capture app for Nextcloud with:
- Camera capture with continuous mode (auto-reopens after each photo)
- File browser with fullscreen image gallery, swipe navigation, and rename
- Upload queue with background sync engine
- Admin panel for Nextcloud user management
- Service worker for offline-first caching (v13)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 04:53:13 -06:00