feat(photos): add square medium variant for sharp grid thumbnails
This commit is contained in:
@@ -61,13 +61,27 @@ func (s *Service) List(ctx context.Context, userID string) ([]models.Album, erro
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// attachCover fills CoverThumbURL from the signed thumbnail URL, when present.
|
||||
// attachCover fills CoverThumbURL and CoverMediumURL from signed URLs. The
|
||||
// medium URL falls back to the thumbnail while the medium variant is not ready,
|
||||
// so a cover URL suitable for large display is always present when a cover is
|
||||
// set.
|
||||
func (s *Service) attachCover(ctx context.Context, a *models.Album) {
|
||||
if s.storage == nil || a == nil || a.CoverThumbKey == "" {
|
||||
if s.storage == nil || a == nil {
|
||||
return
|
||||
}
|
||||
if url, err := s.storage.URL(ctx, a.CoverThumbKey); err == nil {
|
||||
a.CoverThumbURL = url
|
||||
if a.CoverThumbKey != "" {
|
||||
if url, err := s.storage.URL(ctx, a.CoverThumbKey); err == nil {
|
||||
a.CoverThumbURL = url
|
||||
}
|
||||
}
|
||||
key := a.CoverMediumKey
|
||||
if key == "" {
|
||||
key = a.CoverThumbKey
|
||||
}
|
||||
if key != "" {
|
||||
if url, err := s.storage.URL(ctx, key); err == nil {
|
||||
a.CoverMediumURL = url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,20 +46,22 @@ func (s *SQLiteStore) OwnerID(ctx context.Context, id string) (string, error) {
|
||||
}
|
||||
|
||||
const sqliteAlbumColumns = `a.id, a.owner_id, a.title, a.description, a.cover_photo_id,
|
||||
a.created_at, a.updated_at, COALESCE(co.storage_key, ''),
|
||||
a.created_at, a.updated_at, COALESCE(co.storage_key, ''), COALESCE(com.storage_key, ''),
|
||||
(SELECT count(*) FROM photos WHERE album_id = a.id),
|
||||
(SELECT count(*) FROM album_members WHERE album_id = a.id)`
|
||||
|
||||
const sqliteAlbumJoins = `
|
||||
LEFT JOIN photo_objects cpo ON cpo.photo_id = a.cover_photo_id AND cpo.role = 'thumb'
|
||||
LEFT JOIN objects co ON co.id = cpo.object_id`
|
||||
LEFT JOIN objects co ON co.id = cpo.object_id
|
||||
LEFT JOIN photo_objects cpm ON cpm.photo_id = a.cover_photo_id AND cpm.role = 'medium'
|
||||
LEFT JOIN objects com ON com.id = cpm.object_id`
|
||||
|
||||
func scanSQLiteAlbum(scan func(...any) error) (*models.Album, error) {
|
||||
var a models.Album
|
||||
var cover sql.NullString
|
||||
var createdAt, updatedAt string
|
||||
if err := scan(&a.ID, &a.OwnerID, &a.Title, &a.Description, &cover, &createdAt, &updatedAt,
|
||||
&a.CoverThumbKey, &a.PhotosCount, &a.MembersCount); err != nil {
|
||||
&a.CoverThumbKey, &a.CoverMediumKey, &a.PhotosCount, &a.MembersCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cover.Valid {
|
||||
|
||||
@@ -44,14 +44,16 @@ func (s *Store) GetByID(ctx context.Context, id string) (*models.Album, error) {
|
||||
var a models.Album
|
||||
err := s.pool.QueryRow(ctx,
|
||||
`SELECT a.id, a.owner_id, a.title, a.description, a.cover_photo_id, a.created_at, a.updated_at,
|
||||
COALESCE(co.storage_key, ''),
|
||||
COALESCE(co.storage_key, ''), COALESCE(com.storage_key, ''),
|
||||
(SELECT count(*) FROM photos WHERE album_id = a.id),
|
||||
(SELECT count(*) FROM album_members WHERE album_id = a.id)
|
||||
FROM albums a
|
||||
LEFT JOIN photo_objects cpo ON cpo.photo_id = a.cover_photo_id AND cpo.role = 'thumb'
|
||||
LEFT JOIN objects co ON co.id = cpo.object_id
|
||||
LEFT JOIN photo_objects cpm ON cpm.photo_id = a.cover_photo_id AND cpm.role = 'medium'
|
||||
LEFT JOIN objects com ON com.id = cpm.object_id
|
||||
WHERE a.id = $1`, id).
|
||||
Scan(&a.ID, &a.OwnerID, &a.Title, &a.Description, &a.CoverPhotoID, &a.CreatedAt, &a.UpdatedAt, &a.CoverThumbKey, &a.PhotosCount, &a.MembersCount)
|
||||
Scan(&a.ID, &a.OwnerID, &a.Title, &a.Description, &a.CoverPhotoID, &a.CreatedAt, &a.UpdatedAt, &a.CoverThumbKey, &a.CoverMediumKey, &a.PhotosCount, &a.MembersCount)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
@@ -64,13 +66,15 @@ func (s *Store) GetByID(ctx context.Context, id string) (*models.Album, error) {
|
||||
func (s *Store) ListForUser(ctx context.Context, userID string) ([]models.Album, error) {
|
||||
rows, err := s.pool.Query(ctx,
|
||||
`SELECT a.id, a.owner_id, a.title, a.description, a.cover_photo_id, a.created_at, a.updated_at,
|
||||
COALESCE(co.storage_key, ''),
|
||||
COALESCE(co.storage_key, ''), COALESCE(com.storage_key, ''),
|
||||
(SELECT count(*) FROM photos WHERE album_id = a.id),
|
||||
(SELECT count(*) FROM album_members WHERE album_id = a.id)
|
||||
FROM albums a
|
||||
LEFT JOIN album_members m ON m.album_id = a.id AND m.user_id = $1
|
||||
LEFT JOIN photo_objects cpo ON cpo.photo_id = a.cover_photo_id AND cpo.role = 'thumb'
|
||||
LEFT JOIN objects co ON co.id = cpo.object_id
|
||||
LEFT JOIN photo_objects cpm ON cpm.photo_id = a.cover_photo_id AND cpm.role = 'medium'
|
||||
LEFT JOIN objects com ON com.id = cpm.object_id
|
||||
WHERE a.owner_id = $1 OR m.user_id IS NOT NULL
|
||||
ORDER BY a.created_at DESC`, userID)
|
||||
if err != nil {
|
||||
@@ -81,7 +85,7 @@ func (s *Store) ListForUser(ctx context.Context, userID string) ([]models.Album,
|
||||
out := []models.Album{}
|
||||
for rows.Next() {
|
||||
var a models.Album
|
||||
if err := rows.Scan(&a.ID, &a.OwnerID, &a.Title, &a.Description, &a.CoverPhotoID, &a.CreatedAt, &a.UpdatedAt, &a.CoverThumbKey, &a.PhotosCount, &a.MembersCount); err != nil {
|
||||
if err := rows.Scan(&a.ID, &a.OwnerID, &a.Title, &a.Description, &a.CoverPhotoID, &a.CreatedAt, &a.UpdatedAt, &a.CoverThumbKey, &a.CoverMediumKey, &a.PhotosCount, &a.MembersCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, a)
|
||||
|
||||
Reference in New Issue
Block a user