feat(photos): full EXIF metadata extraction, backfill and info panel
- backend: switch EXIF parser to dsoprea/go-exif/v3 (all recognised tags, numeric normalization); store in photos.exif jsonb (migration 000003); add storage.Get and cmd/backfill-exif to backfill existing photos from S3 originals - frontend: info panel renders all EXIF attributes with RU labels, enum translation and units (1/N, f/N, mm, EV); service tags hidden - viewer: remove make-cover action (cover managed from panel only), icon-only download - openspec: sync lightroom-workspace-ui artifacts (EXIF, cover-from-panel) and add plan for configurable info attributes/labels stored in user profile
This commit is contained in:
@@ -122,8 +122,23 @@ func (c *Client) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
return c.Delete(ctx, keys...)
|
||||
}
|
||||
|
||||
func (c *Client) PresignGet(ctx context.Context, key string) (string, error) {
|
||||
out, err := c.presign.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
func (c *Client) Get(ctx context.Context, key string) ([]byte, error) {
|
||||
out, err := c.s3.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(c.bucket),
|
||||
Key: aws.String(key),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get object %s: %w", key, err)
|
||||
}
|
||||
defer out.Body.Close()
|
||||
data, err := io.ReadAll(out.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read object %s: %w", key, err)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (c *Client) PresignGet(ctx context.Context, key string) (string, error) { out, err := c.presign.PresignGetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: aws.String(c.bucket),
|
||||
Key: aws.String(key),
|
||||
}, s3.WithPresignExpires(c.presignTTL))
|
||||
|
||||
Reference in New Issue
Block a user