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:
@@ -22,6 +22,9 @@ type Photo struct {
|
||||
Height int
|
||||
ThumbKey string
|
||||
PreviewKey string
|
||||
// PreviewSizeBytes is the size of the preview object, 0 when it has not
|
||||
// been measured yet (rows written before the column existed).
|
||||
PreviewSizeBytes int64
|
||||
TakenAt time.Time
|
||||
Status string
|
||||
Attempts int
|
||||
@@ -35,11 +38,11 @@ type Photo struct {
|
||||
}
|
||||
|
||||
const photoColumns = `id, gallery_id, position, original_key, original_filename, content_type,
|
||||
size_bytes, width, height, thumb_key, preview_key, taken_at, status, attempts, next_attempt_at,
|
||||
last_error, created_at, updated_at, checksum`
|
||||
size_bytes, width, height, thumb_key, preview_key, preview_size_bytes, taken_at, status,
|
||||
attempts, next_attempt_at, last_error, created_at, updated_at, checksum`
|
||||
|
||||
func scanPhoto(s scanner) (Photo, error) {
|
||||
var v [19]any
|
||||
var v [20]any
|
||||
dest := make([]any, len(v))
|
||||
for i := range v {
|
||||
dest[i] = &v[i]
|
||||
@@ -59,14 +62,15 @@ func scanPhoto(s scanner) (Photo, error) {
|
||||
Height: int(asInt(v[8])),
|
||||
ThumbKey: asString(v[9]),
|
||||
PreviewKey: asString(v[10]),
|
||||
TakenAt: asTime(v[11]),
|
||||
Status: asString(v[12]),
|
||||
Attempts: int(asInt(v[13])),
|
||||
NextAttemptAt: asTime(v[14]),
|
||||
LastError: asString(v[15]),
|
||||
CreatedAt: asTime(v[16]),
|
||||
UpdatedAt: asTime(v[17]),
|
||||
Checksum: asString(v[18]),
|
||||
PreviewSizeBytes: asInt(v[11]),
|
||||
TakenAt: asTime(v[12]),
|
||||
Status: asString(v[13]),
|
||||
Attempts: int(asInt(v[14])),
|
||||
NextAttemptAt: asTime(v[15]),
|
||||
LastError: asString(v[16]),
|
||||
CreatedAt: asTime(v[17]),
|
||||
UpdatedAt: asTime(v[18]),
|
||||
Checksum: asString(v[19]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -323,17 +327,26 @@ func (db *DB) ClaimNextPhoto(ctx context.Context) (Photo, error) {
|
||||
return db.GetPhoto(ctx, id)
|
||||
}
|
||||
|
||||
func (db *DB) MarkPhotoReady(ctx context.Context, id, thumbKey, previewKey string, width, height int, takenAt time.Time) error {
|
||||
func (db *DB) MarkPhotoReady(ctx context.Context, id, thumbKey, previewKey string, previewSize int64, width, height int, takenAt time.Time) error {
|
||||
var takenArg any
|
||||
if !takenAt.IsZero() {
|
||||
takenArg = db.TimeArg(takenAt)
|
||||
}
|
||||
_, err := db.ExecContext(ctx, db.Rebind(`
|
||||
UPDATE photos_photos
|
||||
SET status = 'ready', thumb_key = ?, preview_key = ?, width = ?, height = ?, taken_at = ?,
|
||||
last_error = NULL, updated_at = ?
|
||||
SET status = 'ready', thumb_key = ?, preview_key = ?, preview_size_bytes = ?, width = ?,
|
||||
height = ?, taken_at = ?, last_error = NULL, updated_at = ?
|
||||
WHERE id = ?`),
|
||||
thumbKey, previewKey, width, height, takenArg, db.TimeArg(time.Now()), id)
|
||||
thumbKey, previewKey, previewSize, width, height, takenArg, db.TimeArg(time.Now()), id)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetPreviewSize records the measured size of an already-generated preview.
|
||||
// Used to fill in rows processed before the column existed; failure to write
|
||||
// is not worth failing a read over, so callers may ignore the error.
|
||||
func (db *DB) SetPreviewSize(ctx context.Context, id string, size int64) error {
|
||||
_, err := db.ExecContext(ctx, db.Rebind(
|
||||
"UPDATE photos_photos SET preview_size_bytes = ? WHERE id = ?"), size, id)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user