diff --git a/persistence/album_repository.go b/persistence/album_repository.go index 4217e2cbc..6b2d67964 100644 --- a/persistence/album_repository.go +++ b/persistence/album_repository.go @@ -226,11 +226,13 @@ func (r *albumRepository) UpdateExternalInfo(al *model.Album) error { func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder { sql := r.newSelect(options...).Columns("album.*", "library.path as library_path", "library.name as library_name", // Folds folder image mtimes into the artwork version: an in-place cover swap moves them without - // touching the album row. Parents are included for disc-subfolder layouts, where the reader can - // serve the album-root cover. Bare column (not max()) keeps the decltype so time.Time scans. + // touching the album row. Parents count only when the reader could serve the album-root cover + // (disc subfolders, or a single folder with no images of its own), mirroring albumRootParent's + // first gate. Bare column (not max()) keeps the decltype so time.Time scans. "(select f.images_updated_at from folder f where f.id in"+ " (select je.value from json_each(album.folder_ids) je"+ - " union select p.parent_id from folder p, json_each(album.folder_ids) je2 where p.id = je2.value)"+ + " union select p.parent_id from folder p, json_each(album.folder_ids) je2 where p.id = je2.value"+ + " and (json_array_length(album.folder_ids) > 1 or json_array_length(p.image_files) = 0))"+ " order by f.images_updated_at desc limit 1) as folder_images_updated_at"). LeftJoin("library on album.library_id = library.id") sql = r.withAnnotation(sql, "album.id") diff --git a/persistence/album_repository_test.go b/persistence/album_repository_test.go index 05978af23..ff1ce5aa6 100644 --- a/persistence/album_repository_test.go +++ b/persistence/album_repository_test.go @@ -952,6 +952,25 @@ var _ = Describe("AlbumRepository folder images version", func() { Expect(al.FolderImagesUpdatedAt.Equal(rootAt)).To(BeTrue(), "the parent folder's newer cover must win") }) + It("ignores the parent when the album's single folder has images of its own", func() { + // Mirrors albumRootParent's first gate: the reader would serve the folder's own cover, so an + // unrelated artist-level image must not advance (and suppress) this album's version. + ownAt := time.Date(2030, 6, 1, 12, 0, 0, 0, time.UTC) + parentAt := ownAt.Add(time.Hour) + _, err := GetDBXBuilder().NewQuery( + "insert into folder (id, library_id, path, name, parent_id, images_updated_at, image_files) values" + + " ('fold-blur-root', 1, '.', 'Artist', '', {:parent}, '[\"artist.jpg\"]')," + + " ('fold-blur-1', 1, './Artist', 'Album', 'fold-blur-root', {:own}, '[\"cover.jpg\"]')"). + Bind(map[string]any{"parent": parentAt, "own": ownAt}).Execute() + Expect(err).ToNot(HaveOccurred()) + _, err = GetDBXBuilder().NewQuery(`update album set folder_ids = '["fold-blur-1"]' where id = '103'`).Execute() + Expect(err).ToNot(HaveOccurred()) + + al, err := repo.Get("103") + Expect(err).ToNot(HaveOccurred()) + Expect(al.FolderImagesUpdatedAt).To(HaveValue(Equal(ownAt))) + }) + It("leaves FolderImagesUpdatedAt nil when the album has no folders", func() { al, err := repo.Get("101") Expect(err).ToNot(HaveOccurred())