mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
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:
@@ -30,7 +30,7 @@ const (
|
||||
dbConnTimeout = 30
|
||||
)
|
||||
|
||||
var appSchemaVersion uint = 65
|
||||
var appSchemaVersion uint = 66
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var migrationsBox embed.FS
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
2
pkg/sqlite/migrations/66_gallery_cover.up.sql
Normal file
2
pkg/sqlite/migrations/66_gallery_cover.up.sql
Normal 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;
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user