Support for assigning any image from a gallery as the cover (#5053)

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
sezzim
2024-08-28 18:24:52 -07:00
committed by GitHub
parent 8133aa8c91
commit 68738bd227
23 changed files with 383 additions and 10 deletions

View File

@@ -30,7 +30,7 @@ const (
dbConnTimeout = 30
)
var appSchemaVersion uint = 65
var appSchemaVersion uint = 66
//go:embed migrations/*.sql
var migrationsBox embed.FS

View File

@@ -890,6 +890,14 @@ func (qb *GalleryStore) UpdateImages(ctx context.Context, galleryID int, imageID
return galleryRepository.images.replace(ctx, galleryID, imageIDs)
}
func (qb *GalleryStore) SetCover(ctx context.Context, galleryID int, coverImageID int) error {
return imageGalleriesTableMgr.setCover(ctx, coverImageID, galleryID)
}
func (qb *GalleryStore) ResetCover(ctx context.Context, galleryID int) error {
return imageGalleriesTableMgr.resetCover(ctx, galleryID)
}
func (qb *GalleryStore) GetSceneIDs(ctx context.Context, id int) ([]int, error) {
return galleryRepository.scenes.getIDs(ctx, id)
}

View File

@@ -2973,6 +2973,34 @@ func TestGalleryQueryHasChapters(t *testing.T) {
})
}
func TestGallerySetAndResetCover(t *testing.T) {
withTxn(func(ctx context.Context) error {
sqb := db.Gallery
imagePath2 := getFilePath(folderIdxWithImageFiles, getImageBasename(imageIdx2WithGallery))
result, err := db.Image.CoverByGalleryID(ctx, galleryIDs[galleryIdxWithTwoImages])
assert.Nil(t, err)
assert.Nil(t, result)
err = sqb.SetCover(ctx, galleryIDs[galleryIdxWithTwoImages], imageIDs[imageIdx2WithGallery])
assert.Nil(t, err)
result, err = db.Image.CoverByGalleryID(ctx, galleryIDs[galleryIdxWithTwoImages])
assert.Nil(t, err)
assert.Equal(t, result.Path, imagePath2)
err = sqb.ResetCover(ctx, galleryIDs[galleryIdxWithTwoImages])
assert.Nil(t, err)
result, err = db.Image.CoverByGalleryID(ctx, galleryIDs[galleryIdxWithTwoImages])
assert.Nil(t, err)
assert.Nil(t, result)
return nil
})
}
// TODO Count
// TODO All
// TODO Query

View File

@@ -480,6 +480,42 @@ func (qb *ImageStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*mo
return ret, nil
}
// Returns the custom cover for the gallery, if one has been set.
func (qb *ImageStore) CoverByGalleryID(ctx context.Context, galleryID int) (*models.Image, error) {
table := qb.table()
sq := dialect.From(table).
InnerJoin(
galleriesImagesJoinTable,
goqu.On(table.Col(idColumn).Eq(galleriesImagesJoinTable.Col(imageIDColumn))),
).
Select(table.Col(idColumn)).
Where(goqu.And(
galleriesImagesJoinTable.Col("gallery_id").Eq(galleryID),
galleriesImagesJoinTable.Col("cover").Eq(true),
))
q := qb.selectDataset().Prepared(true).Where(
table.Col(idColumn).Eq(
sq,
),
)
ret, err := qb.getMany(ctx, q)
if err != nil {
return nil, fmt.Errorf("getting cover for gallery %d: %w", galleryID, err)
}
switch {
case len(ret) > 1:
return nil, fmt.Errorf("internal error: multiple covers returned for gallery %d", galleryID)
case len(ret) == 1:
return ret[0], nil
default:
return nil, nil
}
}
func (qb *ImageStore) GetFiles(ctx context.Context, id int) ([]models.File, error) {
fileIDs, err := imageRepository.files.get(ctx, id)
if err != nil {

View File

@@ -0,0 +1,2 @@
ALTER TABLE `galleries_images` ADD COLUMN `cover` BOOLEAN NOT NULL DEFAULT 0;
CREATE UNIQUE INDEX `index_galleries_images_gallery_id_cover` on `galleries_images` (`gallery_id`, `cover`) WHERE `cover` = 1;

View File

@@ -710,6 +710,45 @@ func (t *scenesGroupsTable) modifyJoins(ctx context.Context, id int, v []models.
return nil
}
type imageGalleriesTable struct {
joinTable
}
func (t *imageGalleriesTable) setCover(ctx context.Context, id int, galleryID int) error {
if err := t.resetCover(ctx, galleryID); err != nil {
return err
}
table := t.table.table
q := dialect.Update(table).Prepared(true).Set(goqu.Record{
"cover": true,
}).Where(t.idColumn.Eq(id), table.Col(galleryIDColumn).Eq(galleryID))
if _, err := exec(ctx, q); err != nil {
return fmt.Errorf("setting cover flag in %s: %w", t.table.table.GetTable(), err)
}
return nil
}
func (t *imageGalleriesTable) resetCover(ctx context.Context, galleryID int) error {
table := t.table.table
q := dialect.Update(table).Prepared(true).Set(goqu.Record{
"cover": false,
}).Where(
table.Col(galleryIDColumn).Eq(galleryID),
table.Col("cover").Eq(true),
)
if _, err := exec(ctx, q); err != nil {
return fmt.Errorf("unsetting cover flags in %s: %w", t.table.table.GetTable(), err)
}
return nil
}
type relatedFilesTable struct {
table
}

View File

@@ -57,12 +57,14 @@ var (
},
}
imageGalleriesTableMgr = &joinTable{
table: table{
table: galleriesImagesJoinTable,
idColumn: galleriesImagesJoinTable.Col(imageIDColumn),
imageGalleriesTableMgr = &imageGalleriesTable{
joinTable: joinTable{
table: table{
table: galleriesImagesJoinTable,
idColumn: galleriesImagesJoinTable.Col(imageIDColumn),
},
fkColumn: galleriesImagesJoinTable.Col(galleryIDColumn),
},
fkColumn: galleriesImagesJoinTable.Col(galleryIDColumn),
}
imagesTagsTableMgr = &joinTable{