feat: Add sorting options for Artists

Include both `Album Count` and `Random` sortings for the Artists page.

This change also fixes the Artist search feature in Jellyfin, which was
broken because of an open issue on Jellyfin [1]. The current workaround
is to do the filtering locally after receiving all results from Jellyfin
API.

Also, as the Jellyfin API doesn't include a sorting option for
`AlbumCount`, we need to disable pagination when that option is
selected, to receive all artists, and run the sorting locally.

[1] Related issue: https://github.com/jellyfin/jellyfin/issues/8222
This commit is contained in:
Michael Manganiello
2024-04-13 21:04:51 -03:00
parent 1e05d88a8d
commit 14bfaac7a2
3 changed files with 130 additions and 20 deletions
@@ -2,7 +2,9 @@ package subsonic
import (
"log"
"math/rand"
"slices"
"time"
"golang.org/x/text/collate"
"golang.org/x/text/language"
@@ -14,12 +16,16 @@ import (
)
const (
ArtistSortNameAZ string = "Name (A-Z)"
ArtistSortAlbumCount string = "Album Count"
ArtistSortNameAZ string = "Name (A-Z)"
ArtistSortRandom string = "Random"
)
func (s *subsonicMediaProvider) ArtistSortOrders() []string {
return []string{
ArtistSortAlbumCount,
ArtistSortNameAZ,
ArtistSortRandom,
}
}
@@ -35,6 +41,16 @@ func (s *subsonicMediaProvider) IterateArtists(sortOrder string, filter mediapro
sortOrder = ArtistSortNameAZ // default
}
switch sortOrder {
case ArtistSortAlbumCount:
return s.baseArtistIterFromSimpleSortOrder(
func(artists []*subsonic.ArtistID3) []*subsonic.ArtistID3 {
slices.SortStableFunc(artists, func(a, b *subsonic.ArtistID3) int {
return b.AlbumCount - a.AlbumCount
})
return artists
},
filter,
)
case ArtistSortNameAZ:
return s.baseArtistIterFromSimpleSortOrder(
func(artists []*subsonic.ArtistID3) []*subsonic.ArtistID3 {
@@ -46,6 +62,17 @@ func (s *subsonicMediaProvider) IterateArtists(sortOrder string, filter mediapro
},
filter,
)
case ArtistSortRandom:
return s.baseArtistIterFromSimpleSortOrder(
func(artists []*subsonic.ArtistID3) []*subsonic.ArtistID3 {
newArtists := make([]*subsonic.ArtistID3, len(artists))
copy(newArtists, artists)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
r.Shuffle(len(newArtists), func(i, j int) { newArtists[i], newArtists[j] = newArtists[j], newArtists[i] })
return newArtists
},
filter,
)
default:
log.Printf("Undefined artist sort order: %s", sortOrder)
return nil