feat: image variants per image

This commit is contained in:
fsylvain committed 2026-10-08 19:57:51 +02:00
1 parent f567866161
commit 951fef18ba
92 files changed
+8695 -413

No files matched your search

+48 -9
View File
@@ -16,6 +16,9 @@ type MediaItem struct {
UploadedBy string
UsedIn int
Duplicate bool
VariantCount int
VariantSize int64
}
type MediaCounts struct {
@@ -34,10 +37,11 @@ type ListMediaUseCase struct {
imageRepository image.Repository
articleRepository article.Repository
userRepository user.Repository
variantFiles image.VariantFileRepository
}
func NewListMediaUseCase(imageRepository image.Repository, articleRepository article.Repository, userRepository user.Repository) *ListMediaUseCase {
return &ListMediaUseCase{imageRepository, articleRepository, userRepository}
func NewListMediaUseCase(imageRepository image.Repository, articleRepository article.Repository, userRepository user.Repository, variantFiles image.VariantFileRepository) *ListMediaUseCase {
return &ListMediaUseCase{imageRepository, articleRepository, userRepository, variantFiles}
}
func (l *ListMediaUseCase) List(query image.ListQuery) (MediaPage, error) {
@@ -61,16 +65,20 @@ func (l *ListMediaUseCase) List(query image.ListQuery) (MediaPage, error) {
if err != nil {
return MediaPage{}, err
}
variantTotals, err := l.variantFiles.TotalsBySource()
if err != nil {
return MediaPage{}, err
}
images, err := l.imageRepository.List(image.SearchQuery{Search: strings.TrimSpace(query.Search), Hash: query.Hash})
if err != nil {
return MediaPage{}, err
}
image.SortImages(images, query.Sort)
sortImages(images, query.Sort, variantTotals)
matching := make([]image.Image, 0, len(images))
for _, img := range images {
if matchesFilter(query.Filter, usage(img), duplicateHashes[img.SHA256] && img.SHA256 != "") {
if matchesVariants(query.Variants, variantTotals[image.StoredName(img.Path)].Files) && matchesFilter(query.Filter, usage(img), duplicateHashes[img.SHA256] && img.SHA256 != "") {
matching = append(matching, img)
}
}
@@ -84,11 +92,14 @@ func (l *ListMediaUseCase) List(query image.ListQuery) (MediaPage, error) {
if err != nil {
return MediaPage{}, err
}
own := variantTotals[image.StoredName(img.Path)]
items = append(items, MediaItem{
Image: img,
UploadedBy: uploadedBy,
UsedIn: usage(img),
Duplicate: img.SHA256 != "" && duplicateHashes[img.SHA256],
Image: img,
UploadedBy: uploadedBy,
UsedIn: usage(img),
Duplicate: img.SHA256 != "" && duplicateHashes[img.SHA256],
VariantCount: own.Files,
VariantSize: own.Bytes,
})
}
@@ -118,7 +129,16 @@ func (l *ListMediaUseCase) Describe(img image.Image) (MediaItem, error) {
duplicate = len(sameContent) > 1
}
return MediaItem{Image: img, UploadedBy: uploadedBy, UsedIn: len(articles), Duplicate: duplicate}, nil
rows, err := l.variantFiles.ListBySource(image.StoredName(img.Path))
if err != nil {
return MediaItem{}, err
}
var variantSize int64
for _, row := range rows {
variantSize += row.Size
}
return MediaItem{Image: img, UploadedBy: uploadedBy, UsedIn: len(articles), Duplicate: duplicate, VariantCount: len(rows), VariantSize: variantSize}, nil
}
func (l *ListMediaUseCase) usageCounter() (func(image.Image) int, error) {
@@ -168,6 +188,25 @@ func (l *ListMediaUseCase) counts(usage func(image.Image) int) (MediaCounts, err
return MediaCounts{All: libraryCounts.All, Unused: unused, Duplicates: libraryCounts.DuplicateGroups}, nil
}
func sortImages(images []image.Image, order image.Sort, totals map[string]image.VariantFileTotals) {
if order == image.SortTotalSize {
image.SortImagesByTotalSize(images, totals)
return
}
image.SortImages(images, order)
}
func matchesVariants(filter image.VariantsFilter, variantFiles int) bool {
switch filter {
case image.VariantsWith:
return variantFiles > 0
case image.VariantsWithout:
return variantFiles == 0
default:
return true
}
}
func matchesFilter(filter image.Filter, usedIn int, duplicate bool) bool {
switch filter {
case image.FilterUnused: