mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-28 14:17:10 +01:00
fix(jellyfin): sort album tracks by track number when client sends IndexNumber SortBy
Finamp's album view requests SortBy=ParentIndexNumber,IndexNumber,SortName (disc, track, name), but applySort didn't recognize ParentIndexNumber or IndexNumber and fell through to SortName, sorting tracks alphabetically by title. Map both keys to the album (disc+track) sort. The reversed-title fixture lets the e2e tell track order from title order.
This commit is contained in:
parent
cd18a6fa77
commit
adf943fc87
4 changed files with 37 additions and 13 deletions
|
|
@ -79,10 +79,17 @@ var _ = Describe("Browsing", func() {
|
|||
It("browses an album's tracks in track order by default", func() {
|
||||
q := queryResult(get("/Items?IncludeItemTypes=Audio&ParentId=" + enc(albumID("Abbey Road"))))
|
||||
Expect(q.TotalRecordCount).To(Equal(2))
|
||||
Expect(names(q.Items)).To(Equal([]string{"Come Together", "Something"}))
|
||||
// Track order (Something=1, Come Together=2) differs from alphabetical title order,
|
||||
// proving the sort is by track number, not name.
|
||||
Expect(names(q.Items)).To(Equal([]string{"Something", "Come Together"}))
|
||||
Expect(*q.Items[0].IndexNumber).To(Equal(1))
|
||||
Expect(*q.Items[1].IndexNumber).To(Equal(2))
|
||||
})
|
||||
|
||||
It("respects Finamp's explicit ParentIndexNumber/IndexNumber SortBy on an album", func() {
|
||||
q := queryResult(get("/Items?IncludeItemTypes=Audio&ParentId=" + enc(albumID("Abbey Road")) + "&SortBy=ParentIndexNumber,IndexNumber,SortName"))
|
||||
Expect(names(q.Items)).To(Equal([]string{"Something", "Come Together"}))
|
||||
})
|
||||
})
|
||||
|
||||
// Finamp's artist screen sends ParentId=<libraryId> (scoping) plus AlbumArtistIds/ArtistIds
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
//
|
||||
// # Seeded library (see buildTestFS)
|
||||
//
|
||||
// Rock/The Beatles/Abbey Road/ 01 Come Together (1969), 02 Something (1969)
|
||||
// Rock/The Beatles/Abbey Road/ 01 Something (1969), 02 Come Together (1969)
|
||||
// Rock/The Beatles/Help!/ 01 Help! (1965)
|
||||
// Rock/Led Zeppelin/IV/ 01 Stairway To Heaven (1971)
|
||||
// Jazz/Miles Davis/Kind of Blue/01 So What (1959)
|
||||
|
|
@ -120,8 +120,10 @@ func buildTestFS() storagetest.FakeFS {
|
|||
singles := template(_t{"albumartist": "Solo Artist", "artist": "Solo Artist", "album": "Singles", "year": 2020, "genre": "Pop"})
|
||||
|
||||
return createFS(fstest.MapFS{
|
||||
"Rock/The Beatles/Abbey Road/01 - Come Together.mp3": abbeyRoad(track(1, "Come Together")),
|
||||
"Rock/The Beatles/Abbey Road/02 - Something.mp3": abbeyRoad(track(2, "Something")),
|
||||
// Track numbers are deliberately reversed vs. alphabetical title order (Something=1,
|
||||
// Come Together=2) so tests can tell track-order sorting apart from title sorting.
|
||||
"Rock/The Beatles/Abbey Road/01 - Something.mp3": abbeyRoad(track(1, "Something")),
|
||||
"Rock/The Beatles/Abbey Road/02 - Come Together.mp3": abbeyRoad(track(2, "Come Together")),
|
||||
"Rock/The Beatles/Help!/01 - Help.mp3": help(track(1, "Help!")),
|
||||
"Rock/Led Zeppelin/IV/01 - Stairway To Heaven.mp3": ledZepIV(track(1, "Stairway To Heaven")),
|
||||
"Jazz/Miles Davis/Kind of Blue/01 - So What.mp3": kindOfBlue(track(1, "So What")),
|
||||
|
|
|
|||
|
|
@ -410,14 +410,19 @@ func applySort(opts *model.QueryOptions, itemType, sortBy, order string) {
|
|||
var sortColumnsByType = map[string]map[string]string{
|
||||
"Audio": {
|
||||
"sortname": "title", "name": "title",
|
||||
"album": "album",
|
||||
"artist": "artist",
|
||||
"albumartist": "album_artist",
|
||||
"datecreated": "recently_added",
|
||||
"playcount": "play_count",
|
||||
"dateplayed": "play_date",
|
||||
"communityrating": "rating",
|
||||
"random": "random",
|
||||
"album": "album",
|
||||
// Finamp's album view sorts by ParentIndexNumber,IndexNumber (disc, track). Navidrome's
|
||||
// "album" sort key is order_album_name, album_id, disc_number, track_number, ..., which is
|
||||
// exactly disc+track order within an album, so map both here.
|
||||
"indexnumber": "album",
|
||||
"parentindexnumber": "album",
|
||||
"artist": "artist",
|
||||
"albumartist": "album_artist",
|
||||
"datecreated": "recently_added",
|
||||
"playcount": "play_count",
|
||||
"dateplayed": "play_date",
|
||||
"communityrating": "rating",
|
||||
"random": "random",
|
||||
},
|
||||
"MusicArtist": {
|
||||
"sortname": "name", "name": "name",
|
||||
|
|
|
|||
|
|
@ -288,12 +288,22 @@ var _ = Describe("Items", func() {
|
|||
mfRepo := ds.MediaFile(context.Background()).(*tests.MockMediaFileRepo)
|
||||
mfRepo.SetData(model.MediaFiles{{ID: "s1", Title: "Song"}})
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/Items?IncludeItemTypes=Audio&SortBy=ParentIndexNumber,IndexNumber,SortName", nil).WithContext(ctxUser())
|
||||
r := httptest.NewRequest("GET", "/Items?IncludeItemTypes=Audio&SortBy=Unknown1,Unknown2,SortName", nil).WithContext(ctxUser())
|
||||
api.getItems(w, r)
|
||||
Expect(w.Code).To(Equal(http.StatusOK))
|
||||
Expect(mfRepo.Options.Sort).To(Equal("title"))
|
||||
})
|
||||
|
||||
It("maps Finamp's album view SortBy (ParentIndexNumber,IndexNumber) to disc+track order", func() {
|
||||
mfRepo := ds.MediaFile(context.Background()).(*tests.MockMediaFileRepo)
|
||||
mfRepo.SetData(model.MediaFiles{{ID: "s1", Title: "Song"}})
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/Items?IncludeItemTypes=Audio&SortBy=ParentIndexNumber,IndexNumber,SortName", nil).WithContext(ctxUser())
|
||||
api.getItems(w, r)
|
||||
Expect(w.Code).To(Equal(http.StatusOK))
|
||||
Expect(mfRepo.Options.Sort).To(Equal("album"))
|
||||
})
|
||||
|
||||
It("leaves Sort at the repo default when no SortBy key is recognized", func() {
|
||||
albumRepo := ds.Album(context.Background()).(*tests.MockAlbumRepo)
|
||||
albumRepo.SetData(model.Albums{{ID: "a1", Name: "One"}})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue