Add mobile save sheet with same-origin photo downloads.

Phones cannot land downloads in the photo library, so the gallery opens a share sheet for a cacheable preview while streaming via a dedicated download endpoint and recording preview sizes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michilis
2026-08-06 20:14:31 +00:00
co-authored by Cursor
parent 390e1dc0ea
commit be4dd5b47f
20 changed files with 962 additions and 56 deletions
+14 -7
View File
@@ -146,14 +146,17 @@ func (w *Worker) process(ctx context.Context, p store.Photo) error {
prefix := fmt.Sprintf("galleries/%s", p.GalleryID)
thumbKey := fmt.Sprintf("%s/thumb/%s.jpg", prefix, base)
previewKey := fmt.Sprintf("%s/preview/%s.jpg", prefix, base)
if err := w.upload(ctx, thumbKey, thumbPath); err != nil {
if _, err := w.upload(ctx, thumbKey, thumbPath); err != nil {
return fmt.Errorf("store thumb: %w", err)
}
if err := w.upload(ctx, previewKey, previewPath); err != nil {
// The preview's size is recorded because the gallery response labels the
// mobile save sheet with it; measuring it here costs nothing.
previewSize, err := w.upload(ctx, previewKey, previewPath)
if err != nil {
return fmt.Errorf("store preview: %w", err)
}
return w.db.MarkPhotoReady(ctx, p.ID, thumbKey, previewKey, res.Width, res.Height, res.TakenAt)
return w.db.MarkPhotoReady(ctx, p.ID, thumbKey, previewKey, previewSize, res.Width, res.Height, res.TakenAt)
}
func (w *Worker) download(ctx context.Context, key, dst string) error {
@@ -171,15 +174,19 @@ func (w *Worker) download(ctx context.Context, key, dst string) error {
return err
}
func (w *Worker) upload(ctx context.Context, key, src string) error {
// upload stores a generated variant and reports how many bytes it holds.
func (w *Worker) upload(ctx context.Context, key, src string) (int64, error) {
f, err := os.Open(src)
if err != nil {
return err
return 0, err
}
defer f.Close()
info, err := f.Stat()
if err != nil {
return err
return 0, err
}
return w.storage.Put(ctx, key, f, info.Size(), "image/jpeg")
if err := w.storage.Put(ctx, key, f, info.Size(), "image/jpeg"); err != nil {
return 0, err
}
return info.Size(), nil
}