Browse Source

Convert ItemSortBy to enum (#9765)

* Convert ItemSortBy to enum

* Rename Unknown to Default
Cody Robibero 1 năm trước cách đây
mục cha
commit
c7a94d48ae
55 tập tin đã thay đổi với 329 bổ sung416 xóa
  1. 9 9
      Emby.Dlna/ContentDirectory/ControlHandler.cs
  2. 41 164
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  3. 1 1
      Emby.Server.Implementations/Images/BaseFolderImageProvider.cs
  4. 4 4
      Emby.Server.Implementations/Library/LibraryManager.cs
  5. 1 1
      Emby.Server.Implementations/LiveTv/LiveTvManager.cs
  6. 2 1
      Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
  7. 2 1
      Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs
  8. 2 1
      Emby.Server.Implementations/Sorting/AlbumComparer.cs
  9. 2 1
      Emby.Server.Implementations/Sorting/ArtistComparer.cs
  10. 2 1
      Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs
  11. 2 1
      Emby.Server.Implementations/Sorting/CriticRatingComparer.cs
  12. 2 1
      Emby.Server.Implementations/Sorting/DateCreatedComparer.cs
  13. 2 1
      Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs
  14. 2 1
      Emby.Server.Implementations/Sorting/DatePlayedComparer.cs
  15. 2 1
      Emby.Server.Implementations/Sorting/IndexNumberComparer.cs
  16. 2 1
      Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs
  17. 2 1
      Emby.Server.Implementations/Sorting/IsFolderComparer.cs
  18. 2 1
      Emby.Server.Implementations/Sorting/IsPlayedComparer.cs
  19. 2 1
      Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs
  20. 2 1
      Emby.Server.Implementations/Sorting/NameComparer.cs
  21. 2 1
      Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs
  22. 2 1
      Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs
  23. 2 1
      Emby.Server.Implementations/Sorting/PlayCountComparer.cs
  24. 2 1
      Emby.Server.Implementations/Sorting/PremiereDateComparer.cs
  25. 2 1
      Emby.Server.Implementations/Sorting/ProductionYearComparer.cs
  26. 2 1
      Emby.Server.Implementations/Sorting/RandomComparer.cs
  27. 2 1
      Emby.Server.Implementations/Sorting/RuntimeComparer.cs
  28. 2 1
      Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs
  29. 2 1
      Emby.Server.Implementations/Sorting/SortNameComparer.cs
  30. 2 1
      Emby.Server.Implementations/Sorting/StartDateComparer.cs
  31. 2 1
      Emby.Server.Implementations/Sorting/StudioComparer.cs
  32. 2 2
      Jellyfin.Api/Controllers/ArtistsController.cs
  33. 1 1
      Jellyfin.Api/Controllers/ChannelsController.cs
  34. 1 1
      Jellyfin.Api/Controllers/GenresController.cs
  35. 2 2
      Jellyfin.Api/Controllers/ItemsController.cs
  36. 2 2
      Jellyfin.Api/Controllers/LiveTvController.cs
  37. 1 1
      Jellyfin.Api/Controllers/MusicGenresController.cs
  38. 1 1
      Jellyfin.Api/Controllers/TrailersController.cs
  39. 2 2
      Jellyfin.Api/Controllers/TvShowsController.cs
  40. 1 1
      Jellyfin.Api/Controllers/YearsController.cs
  41. 3 3
      Jellyfin.Api/Helpers/RequestHelpers.cs
  42. 1 1
      Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs
  43. 167 0
      Jellyfin.Data/Enums/ItemSortBy.cs
  44. 2 0
      MediaBrowser.Controller/Entities/IHasDisplayOrder.cs
  45. 2 2
      MediaBrowser.Controller/Entities/InternalItemsQuery.cs
  46. 4 4
      MediaBrowser.Controller/Entities/Movies/BoxSet.cs
  47. 2 2
      MediaBrowser.Controller/Library/ILibraryManager.cs
  48. 1 0
      MediaBrowser.Controller/Providers/EpisodeInfo.cs
  49. 3 3
      MediaBrowser.Controller/Sorting/IBaseItemComparer.cs
  50. 1 0
      MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
  51. 2 2
      MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs
  52. 0 163
      MediaBrowser.Model/Querying/ItemSortBy.cs
  53. 1 0
      MediaBrowser.Providers/Manager/MetadataService.cs
  54. 1 0
      MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
  55. 18 18
      tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs

+ 9 - 9
Emby.Dlna/ContentDirectory/ControlHandler.cs

@@ -917,7 +917,7 @@ namespace Emby.Dlna.ContentDirectory
         private QueryResult<ServerItem> GetGenres(BaseItem parent, InternalItemsQuery query)
         {
             // Don't sort
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             query.AncestorIds = new[] { parent.Id };
             var genresResult = _libraryManager.GetGenres(query);
 
@@ -933,7 +933,7 @@ namespace Emby.Dlna.ContentDirectory
         private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, InternalItemsQuery query)
         {
             // Don't sort
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             query.AncestorIds = new[] { parent.Id };
             var genresResult = _libraryManager.GetMusicGenres(query);
 
@@ -949,7 +949,7 @@ namespace Emby.Dlna.ContentDirectory
         private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, InternalItemsQuery query)
         {
             // Don't sort
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             query.AncestorIds = new[] { parent.Id };
             var artists = _libraryManager.GetAlbumArtists(query);
 
@@ -965,7 +965,7 @@ namespace Emby.Dlna.ContentDirectory
         private QueryResult<ServerItem> GetMusicArtists(BaseItem parent, InternalItemsQuery query)
         {
             // Don't sort
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             query.AncestorIds = new[] { parent.Id };
             var artists = _libraryManager.GetArtists(query);
             return ToResult(query.StartIndex, artists);
@@ -980,7 +980,7 @@ namespace Emby.Dlna.ContentDirectory
         private QueryResult<ServerItem> GetFavoriteArtists(BaseItem parent, InternalItemsQuery query)
         {
             // Don't sort
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             query.AncestorIds = new[] { parent.Id };
             query.IsFavorite = true;
             var artists = _libraryManager.GetArtists(query);
@@ -1011,7 +1011,7 @@ namespace Emby.Dlna.ContentDirectory
         /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
         private QueryResult<ServerItem> GetNextUp(BaseItem parent, InternalItemsQuery query)
         {
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
 
             var result = _tvSeriesManager.GetNextUp(
                 new NextUpQuery
@@ -1036,7 +1036,7 @@ namespace Emby.Dlna.ContentDirectory
         /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
         private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery query, BaseItemKind itemType)
         {
-            query.OrderBy = Array.Empty<(string, SortOrder)>();
+            query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
 
             var items = _userViewManager.GetLatestItems(
                 new LatestItemsQuery
@@ -1203,9 +1203,9 @@ namespace Emby.Dlna.ContentDirectory
         /// </summary>
         /// <param name="sort">The <see cref="SortCriteria"/>.</param>
         /// <param name="isPreSorted">True if pre-sorted.</param>
-        private static (string SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted)
+        private static (ItemSortBy SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted)
         {
-            return isPreSorted ? Array.Empty<(string, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) };
+            return isPreSorted ? Array.Empty<(ItemSortBy, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) };
         }
 
         /// <summary>

+ 41 - 164
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -2042,7 +2042,7 @@ namespace Emby.Server.Implementations.Data
                 return false;
             }
 
-            var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.OrderBy), StringComparer.OrdinalIgnoreCase);
+            var sortingFields = new HashSet<ItemSortBy>(query.OrderBy.Select(i => i.OrderBy));
 
             return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked)
                     || sortingFields.Contains(ItemSortBy.IsPlayed)
@@ -2832,20 +2832,20 @@ namespace Emby.Server.Implementations.Data
 
             if (hasSimilar || hasSearch)
             {
-                List<(string, SortOrder)> prepend = new List<(string, SortOrder)>(4);
+                List<(ItemSortBy, SortOrder)> prepend = new List<(ItemSortBy, SortOrder)>(4);
                 if (hasSearch)
                 {
-                    prepend.Add(("SearchScore", SortOrder.Descending));
+                    prepend.Add((ItemSortBy.SearchScore, SortOrder.Descending));
                     prepend.Add((ItemSortBy.SortName, SortOrder.Ascending));
                 }
 
                 if (hasSimilar)
                 {
-                    prepend.Add(("SimilarityScore", SortOrder.Descending));
+                    prepend.Add((ItemSortBy.SimilarityScore, SortOrder.Descending));
                     prepend.Add((ItemSortBy.Random, SortOrder.Ascending));
                 }
 
-                var arr = new (string, SortOrder)[prepend.Count + orderBy.Count];
+                var arr = new (ItemSortBy, SortOrder)[prepend.Count + orderBy.Count];
                 prepend.CopyTo(arr, 0);
                 orderBy.CopyTo(arr, prepend.Count);
                 orderBy = query.OrderBy = arr;
@@ -2863,166 +2863,43 @@ namespace Emby.Server.Implementations.Data
             }));
         }
 
-        private string MapOrderByField(string name, InternalItemsQuery query)
+        private string MapOrderByField(ItemSortBy sortBy, InternalItemsQuery query)
         {
-            if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
-            {
-                // TODO
-                return "SortName";
-            }
-
-            if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase))
-            {
-                return "RuntimeTicks";
-            }
-
-            if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
-            {
-                return "RANDOM()";
-            }
-
-            if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase))
-            {
-                if (query.GroupBySeriesPresentationUniqueKey)
-                {
-                    return "MAX(LastPlayedDate)";
-                }
-
-                return "LastPlayedDate";
-            }
-
-            if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.PlayCount;
-            }
-
-            if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase))
-            {
-                return "(Select Case When IsFavorite is null Then 0 Else IsFavorite End )";
-            }
-
-            if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.IsFolder;
-            }
-
-            if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase))
-            {
-                return "played";
-            }
-
-            if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase))
-            {
-                return "played";
-            }
-
-            if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase))
-            {
-                return "DateLastMediaAdded";
-            }
-
-            if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase))
-            {
-                return "(select CleanValue from ItemValues where ItemId=Guid and Type=0 LIMIT 1)";
-            }
-
-            if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase))
-            {
-                return "(select CleanValue from ItemValues where ItemId=Guid and Type=1 LIMIT 1)";
-            }
-
-            if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase))
-            {
-                return "InheritedParentalRatingValue";
-            }
-
-            if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase))
-            {
-                return "(select CleanValue from ItemValues where ItemId=Guid and Type=3 LIMIT 1)";
-            }
-
-            if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase))
-            {
-                return "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)";
-            }
-
-            if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase))
-            {
-                return "SeriesName";
-            }
-
-            if (string.Equals(name, ItemSortBy.AiredEpisodeOrder, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.AiredEpisodeOrder;
-            }
-
-            if (string.Equals(name, ItemSortBy.Album, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.Album;
-            }
-
-            if (string.Equals(name, ItemSortBy.DateCreated, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.DateCreated;
-            }
-
-            if (string.Equals(name, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.PremiereDate;
-            }
-
-            if (string.Equals(name, ItemSortBy.StartDate, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.StartDate;
-            }
-
-            if (string.Equals(name, ItemSortBy.Name, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.Name;
-            }
-
-            if (string.Equals(name, ItemSortBy.CommunityRating, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.CommunityRating;
-            }
-
-            if (string.Equals(name, ItemSortBy.ProductionYear, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.ProductionYear;
-            }
-
-            if (string.Equals(name, ItemSortBy.CriticRating, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.CriticRating;
-            }
-
-            if (string.Equals(name, ItemSortBy.VideoBitRate, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.VideoBitRate;
-            }
-
-            if (string.Equals(name, ItemSortBy.ParentIndexNumber, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.ParentIndexNumber;
-            }
-
-            if (string.Equals(name, ItemSortBy.IndexNumber, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.IndexNumber;
-            }
-
-            if (string.Equals(name, ItemSortBy.SimilarityScore, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.SimilarityScore;
-            }
-
-            if (string.Equals(name, ItemSortBy.SearchScore, StringComparison.OrdinalIgnoreCase))
-            {
-                return ItemSortBy.SearchScore;
-            }
-
-            // Unknown SortBy, just sort by the SortName.
-            return ItemSortBy.SortName;
+            return sortBy switch
+            {
+                ItemSortBy.AirTime => "SortName", // TODO
+                ItemSortBy.Runtime => "RuntimeTicks",
+                ItemSortBy.Random => "RANDOM()",
+                ItemSortBy.DatePlayed when query.GroupBySeriesPresentationUniqueKey => "MAX(LastPlayedDate)",
+                ItemSortBy.DatePlayed => "LastPlayedDate",
+                ItemSortBy.PlayCount => "PlayCount",
+                ItemSortBy.IsFavoriteOrLiked => "(Select Case When IsFavorite is null Then 0 Else IsFavorite End )",
+                ItemSortBy.IsFolder => "IsFolder",
+                ItemSortBy.IsPlayed => "played",
+                ItemSortBy.IsUnplayed => "played",
+                ItemSortBy.DateLastContentAdded => "DateLastMediaAdded",
+                ItemSortBy.Artist => "(select CleanValue from ItemValues where ItemId=Guid and Type=0 LIMIT 1)",
+                ItemSortBy.AlbumArtist => "(select CleanValue from ItemValues where ItemId=Guid and Type=1 LIMIT 1)",
+                ItemSortBy.OfficialRating => "InheritedParentalRatingValue",
+                ItemSortBy.Studio => "(select CleanValue from ItemValues where ItemId=Guid and Type=3 LIMIT 1)",
+                ItemSortBy.SeriesDatePlayed => "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)",
+                ItemSortBy.SeriesSortName => "SeriesName",
+                ItemSortBy.AiredEpisodeOrder => "AiredEpisodeOrder",
+                ItemSortBy.Album => "Album",
+                ItemSortBy.DateCreated => "DateCreated",
+                ItemSortBy.PremiereDate => "PremiereDate",
+                ItemSortBy.StartDate => "StartDate",
+                ItemSortBy.Name => "Name",
+                ItemSortBy.CommunityRating => "CommunityRating",
+                ItemSortBy.ProductionYear => "ProductionYear",
+                ItemSortBy.CriticRating => "CriticRating",
+                ItemSortBy.VideoBitRate => "VideoBitRate",
+                ItemSortBy.ParentIndexNumber => "ParentIndexNumber",
+                ItemSortBy.IndexNumber => "IndexNumber",
+                ItemSortBy.SimilarityScore => "SimilarityScore",
+                ItemSortBy.SearchScore => "SearchScore",
+                _ => "SortName"
+            };
         }
 
         public List<Guid> GetItemIdsList(InternalItemsQuery query)

+ 1 - 1
Emby.Server.Implementations/Images/BaseFolderImageProvider.cs

@@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Images
                 Recursive = true,
                 DtoOptions = new DtoOptions(true),
                 ImageTypes = new ImageType[] { ImageType.Primary },
-                OrderBy = new (string, SortOrder)[]
+                OrderBy = new (ItemSortBy, SortOrder)[]
                 {
                     (ItemSortBy.IsFolder, SortOrder.Ascending),
                     (ItemSortBy.SortName, SortOrder.Ascending)

+ 4 - 4
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -1678,7 +1678,7 @@ namespace Emby.Server.Implementations.Library
         /// <param name="sortBy">The sort by.</param>
         /// <param name="sortOrder">The sort order.</param>
         /// <returns>IEnumerable{BaseItem}.</returns>
-        public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder)
+        public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder)
         {
             var isFirst = true;
 
@@ -1701,7 +1701,7 @@ namespace Emby.Server.Implementations.Library
             return orderedItems ?? items;
         }
 
-        public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy)
+        public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy)
         {
             var isFirst = true;
 
@@ -1736,9 +1736,9 @@ namespace Emby.Server.Implementations.Library
         /// <param name="name">The name.</param>
         /// <param name="user">The user.</param>
         /// <returns>IBaseItemComparer.</returns>
-        private IBaseItemComparer GetComparer(string name, User user)
+        private IBaseItemComparer GetComparer(ItemSortBy name, User user)
         {
-            var comparer = Comparers.FirstOrDefault(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase));
+            var comparer = Comparers.FirstOrDefault(c => name == c.Type);
 
             // If it requires a user, create a new one, and assign the user
             if (comparer is IUserBaseItemComparer)

+ 1 - 1
Emby.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.LiveTv
                 orderBy.Insert(0, (ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
             }
 
-            if (!internalQuery.OrderBy.Any(i => string.Equals(i.OrderBy, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
+            if (internalQuery.OrderBy.All(i => i.OrderBy != ItemSortBy.SortName))
             {
                 orderBy.Add((ItemSortBy.SortName, SortOrder.Ascending));
             }

+ 2 - 1
Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Sorting;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.AiredEpisodeOrder;
+        public ItemSortBy Type => ItemSortBy.AiredEpisodeOrder;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Linq;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Sorting;
@@ -16,7 +17,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.AlbumArtist;
+        public ItemSortBy Type => ItemSortBy.AlbumArtist;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/AlbumComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Sorting;
@@ -15,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.Album;
+        public ItemSortBy Type => ItemSortBy.Album;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/ArtistComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Sorting;
@@ -12,7 +13,7 @@ namespace Emby.Server.Implementations.Sorting
     public class ArtistComparer : IBaseItemComparer
     {
         /// <inheritdoc />
-        public string Name => ItemSortBy.Artist;
+        public ItemSortBy Type => ItemSortBy.Artist;
 
         /// <inheritdoc />
         public int Compare(BaseItem? x, BaseItem? y)

+ 2 - 1
Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.CommunityRating;
+        public ItemSortBy Type => ItemSortBy.CommunityRating;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/CriticRatingComparer.cs

@@ -1,3 +1,4 @@
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.CriticRating;
+        public ItemSortBy Type => ItemSortBy.CriticRating;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/DateCreatedComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.DateCreated;
+        public ItemSortBy Type => ItemSortBy.DateCreated;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs

@@ -3,6 +3,7 @@
 
 using System;
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -34,7 +35,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.DateLastContentAdded;
+        public ItemSortBy Type => ItemSortBy.DateLastContentAdded;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/DatePlayedComparer.cs

@@ -2,6 +2,7 @@
 
 using System;
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -36,7 +37,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.DatePlayed;
+        public ItemSortBy Type => ItemSortBy.DatePlayed;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/IndexNumberComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.IndexNumber;
+        public ItemSortBy Type => ItemSortBy.IndexNumber;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs

@@ -2,6 +2,7 @@
 #pragma warning disable CS1591
 
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.IsFavoriteOrLiked;
+        public ItemSortBy Type => ItemSortBy.IsFavoriteOrLiked;
 
         /// <summary>
         /// Gets or sets the user data repository.

+ 2 - 1
Emby.Server.Implementations/Sorting/IsFolderComparer.cs

@@ -1,5 +1,6 @@
 #pragma warning disable CS1591
 
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -12,7 +13,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.IsFolder;
+        public ItemSortBy Type => ItemSortBy.IsFolder;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/IsPlayedComparer.cs

@@ -3,6 +3,7 @@
 #pragma warning disable CS1591
 
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -22,7 +23,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.IsUnplayed;
+        public ItemSortBy Type => ItemSortBy.IsUnplayed;
 
         /// <summary>
         /// Gets or sets the user data repository.

+ 2 - 1
Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs

@@ -3,6 +3,7 @@
 #pragma warning disable CS1591
 
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -22,7 +23,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.IsUnplayed;
+        public ItemSortBy Type => ItemSortBy.IsUnplayed;
 
         /// <summary>
         /// Gets or sets the user data repository.

+ 2 - 1
Emby.Server.Implementations/Sorting/NameComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.Name;
+        public ItemSortBy Type => ItemSortBy.Name;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Globalization;
@@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.OfficialRating;
+        public ItemSortBy Type => ItemSortBy.OfficialRating;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.ParentIndexNumber;
+        public ItemSortBy Type => ItemSortBy.ParentIndexNumber;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/PlayCountComparer.cs

@@ -1,6 +1,7 @@
 #nullable disable
 
 using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Sorting;
@@ -23,7 +24,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.PlayCount;
+        public ItemSortBy Type => ItemSortBy.PlayCount;
 
         /// <summary>
         /// Gets or sets the user data repository.

+ 2 - 1
Emby.Server.Implementations/Sorting/PremiereDateComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.PremiereDate;
+        public ItemSortBy Type => ItemSortBy.PremiereDate;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/ProductionYearComparer.cs

@@ -1,3 +1,4 @@
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.ProductionYear;
+        public ItemSortBy Type => ItemSortBy.ProductionYear;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/RandomComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.Random;
+        public ItemSortBy Type => ItemSortBy.Random;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/RuntimeComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.Runtime;
+        public ItemSortBy Type => ItemSortBy.Runtime;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.SeriesSortName;
+        public ItemSortBy Type => ItemSortBy.SeriesSortName;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/SortNameComparer.cs

@@ -1,4 +1,5 @@
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
 using MediaBrowser.Model.Querying;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.SortName;
+        public ItemSortBy Type => ItemSortBy.SortName;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/StartDateComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Controller.Sorting;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.StartDate;
+        public ItemSortBy Type => ItemSortBy.StartDate;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 1
Emby.Server.Implementations/Sorting/StudioComparer.cs

@@ -1,6 +1,7 @@
 #pragma warning disable CS1591
 
 using System;
+using Jellyfin.Data.Enums;
 using Jellyfin.Extensions;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Sorting;
@@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting
         /// Gets the name.
         /// </summary>
         /// <value>The name.</value>
-        public string Name => ItemSortBy.Studio;
+        public ItemSortBy Type => ItemSortBy.Studio;
 
         /// <summary>
         /// Compares the specified x.

+ 2 - 2
Jellyfin.Api/Controllers/ArtistsController.cs

@@ -113,7 +113,7 @@ public class ArtistsController : BaseJellyfinApiController
         [FromQuery] string? nameStartsWithOrGreater,
         [FromQuery] string? nameStartsWith,
         [FromQuery] string? nameLessThan,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery] bool? enableImages = true,
         [FromQuery] bool enableTotalRecordCount = true)
@@ -317,7 +317,7 @@ public class ArtistsController : BaseJellyfinApiController
         [FromQuery] string? nameStartsWithOrGreater,
         [FromQuery] string? nameStartsWith,
         [FromQuery] string? nameLessThan,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery] bool? enableImages = true,
         [FromQuery] bool enableTotalRecordCount = true)

+ 1 - 1
Jellyfin.Api/Controllers/ChannelsController.cs

@@ -122,7 +122,7 @@ public class ChannelsController : BaseJellyfinApiController
         [FromQuery] int? limit,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields)
     {
         userId = RequestHelpers.GetUserId(User, userId);

+ 1 - 1
Jellyfin.Api/Controllers/GenresController.cs

@@ -85,7 +85,7 @@ public class GenresController : BaseJellyfinApiController
         [FromQuery] string? nameStartsWithOrGreater,
         [FromQuery] string? nameStartsWith,
         [FromQuery] string? nameLessThan,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery] bool? enableImages = true,
         [FromQuery] bool enableTotalRecordCount = true)

+ 2 - 2
Jellyfin.Api/Controllers/ItemsController.cs

@@ -197,7 +197,7 @@ public class ItemsController : BaseJellyfinApiController
         [FromQuery] bool? isFavorite,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery] bool? isPlayed,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings,
@@ -654,7 +654,7 @@ public class ItemsController : BaseJellyfinApiController
         [FromQuery] bool? isFavorite,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery] bool? isPlayed,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings,

+ 2 - 2
Jellyfin.Api/Controllers/LiveTvController.cs

@@ -143,7 +143,7 @@ public class LiveTvController : BaseJellyfinApiController
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
         [FromQuery] bool? enableUserData,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery] SortOrder? sortOrder,
         [FromQuery] bool enableFavoriteSorting = false,
         [FromQuery] bool addCurrentProgram = true)
@@ -547,7 +547,7 @@ public class LiveTvController : BaseJellyfinApiController
         [FromQuery] bool? isSports,
         [FromQuery] int? startIndex,
         [FromQuery] int? limit,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds,

+ 1 - 1
Jellyfin.Api/Controllers/MusicGenresController.cs

@@ -85,7 +85,7 @@ public class MusicGenresController : BaseJellyfinApiController
         [FromQuery] string? nameStartsWithOrGreater,
         [FromQuery] string? nameStartsWith,
         [FromQuery] string? nameLessThan,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
         [FromQuery] bool? enableImages = true,
         [FromQuery] bool enableTotalRecordCount = true)

+ 1 - 1
Jellyfin.Api/Controllers/TrailersController.cs

@@ -162,7 +162,7 @@ public class TrailersController : BaseJellyfinApiController
         [FromQuery] bool? isFavorite,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery] bool? isPlayed,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres,
         [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings,

+ 2 - 2
Jellyfin.Api/Controllers/TvShowsController.cs

@@ -219,7 +219,7 @@ public class TvShowsController : BaseJellyfinApiController
         [FromQuery] int? imageTypeLimit,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
         [FromQuery] bool? enableUserData,
-        [FromQuery] string? sortBy)
+        [FromQuery] ItemSortBy? sortBy)
     {
         userId = RequestHelpers.GetUserId(User, userId);
         var user = userId.Value.Equals(default)
@@ -289,7 +289,7 @@ public class TvShowsController : BaseJellyfinApiController
             episodes = UserViewBuilder.FilterForAdjacency(episodes, adjacentTo.Value).ToList();
         }
 
-        if (string.Equals(sortBy, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
+        if (sortBy == ItemSortBy.Random)
         {
             episodes.Shuffle();
         }

+ 1 - 1
Jellyfin.Api/Controllers/YearsController.cs

@@ -77,7 +77,7 @@ public class YearsController : BaseJellyfinApiController
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
-        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
+        [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy,
         [FromQuery] bool? enableUserData,
         [FromQuery] int? imageTypeLimit,
         [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,

+ 3 - 3
Jellyfin.Api/Helpers/RequestHelpers.cs

@@ -30,14 +30,14 @@ public static class RequestHelpers
     /// <param name="sortBy">Sort By. Comma delimited string.</param>
     /// <param name="requestedSortOrder">Sort Order. Comma delimited string.</param>
     /// <returns>Order By.</returns>
-    public static (string, SortOrder)[] GetOrderBy(IReadOnlyList<string> sortBy, IReadOnlyList<SortOrder> requestedSortOrder)
+    public static (ItemSortBy, SortOrder)[] GetOrderBy(IReadOnlyList<ItemSortBy> sortBy, IReadOnlyList<SortOrder> requestedSortOrder)
     {
         if (sortBy.Count == 0)
         {
-            return Array.Empty<(string, SortOrder)>();
+            return Array.Empty<(ItemSortBy, SortOrder)>();
         }
 
-        var result = new (string, SortOrder)[sortBy.Count];
+        var result = new (ItemSortBy, SortOrder)[sortBy.Count];
         var i = 0;
         // Add elements which have a SortOrder specified
         for (; i < requestedSortOrder.Count; i++)

+ 1 - 1
Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs

@@ -107,7 +107,7 @@ public class GetProgramsDto
     /// Optional.
     /// </summary>
     [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
-    public IReadOnlyList<string> SortBy { get; set; } = Array.Empty<string>();
+    public IReadOnlyList<ItemSortBy> SortBy { get; set; } = Array.Empty<ItemSortBy>();
 
     /// <summary>
     /// Gets or sets sort Order - Ascending,Descending.

+ 167 - 0
Jellyfin.Data/Enums/ItemSortBy.cs

@@ -0,0 +1,167 @@
+namespace Jellyfin.Data.Enums;
+
+/// <summary>
+/// These represent sort orders.
+/// </summary>
+public enum ItemSortBy
+{
+    /// <summary>
+    /// Default sort order.
+    /// </summary>
+    Default = 0,
+
+    /// <summary>
+    /// The aired episode order.
+    /// </summary>
+    AiredEpisodeOrder = 1,
+
+    /// <summary>
+    /// The album.
+    /// </summary>
+    Album = 2,
+
+    /// <summary>
+    /// The album artist.
+    /// </summary>
+    AlbumArtist = 3,
+
+    /// <summary>
+    /// The artist.
+    /// </summary>
+    Artist = 4,
+
+    /// <summary>
+    /// The date created.
+    /// </summary>
+    DateCreated = 5,
+
+    /// <summary>
+    /// The official rating.
+    /// </summary>
+    OfficialRating = 6,
+
+    /// <summary>
+    /// The date played.
+    /// </summary>
+    DatePlayed = 7,
+
+    /// <summary>
+    /// The premiere date.
+    /// </summary>
+    PremiereDate = 8,
+
+    /// <summary>
+    /// The start date.
+    /// </summary>
+    StartDate = 9,
+
+    /// <summary>
+    /// The sort name.
+    /// </summary>
+    SortName = 10,
+
+    /// <summary>
+    /// The name.
+    /// </summary>
+    Name = 11,
+
+    /// <summary>
+    /// The random.
+    /// </summary>
+    Random = 12,
+
+    /// <summary>
+    /// The runtime.
+    /// </summary>
+    Runtime = 13,
+
+    /// <summary>
+    /// The community rating.
+    /// </summary>
+    CommunityRating = 14,
+
+    /// <summary>
+    /// The production year.
+    /// </summary>
+    ProductionYear = 15,
+
+    /// <summary>
+    /// The play count.
+    /// </summary>
+    PlayCount = 16,
+
+    /// <summary>
+    /// The critic rating.
+    /// </summary>
+    CriticRating = 17,
+
+    /// <summary>
+    /// The IsFolder boolean.
+    /// </summary>
+    IsFolder = 18,
+
+    /// <summary>
+    /// The IsUnplayed boolean.
+    /// </summary>
+    IsUnplayed = 19,
+
+    /// <summary>
+    /// The IsPlayed boolean.
+    /// </summary>
+    IsPlayed = 20,
+
+    /// <summary>
+    /// The series sort.
+    /// </summary>
+    SeriesSortName = 21,
+
+    /// <summary>
+    /// The video bitrate.
+    /// </summary>
+    VideoBitRate = 22,
+
+    /// <summary>
+    /// The air time.
+    /// </summary>
+    AirTime = 23,
+
+    /// <summary>
+    /// The studio.
+    /// </summary>
+    Studio = 24,
+
+    /// <summary>
+    /// The IsFavouriteOrLiked boolean.
+    /// </summary>
+    IsFavoriteOrLiked = 25,
+
+    /// <summary>
+    /// The last content added date.
+    /// </summary>
+    DateLastContentAdded = 26,
+
+    /// <summary>
+    /// The series last played date.
+    /// </summary>
+    SeriesDatePlayed = 27,
+
+    /// <summary>
+    /// The parent index number.
+    /// </summary>
+    ParentIndexNumber = 28,
+
+    /// <summary>
+    /// The index number.
+    /// </summary>
+    IndexNumber = 29,
+
+    /// <summary>
+    /// The similarity score.
+    /// </summary>
+    SimilarityScore = 30,
+
+    /// <summary>
+    /// The search score.
+    /// </summary>
+    SearchScore = 31,
+}

+ 2 - 0
MediaBrowser.Controller/Entities/IHasDisplayOrder.cs

@@ -1,5 +1,7 @@
 #nullable disable
 
+using Jellyfin.Data.Enums;
+
 namespace MediaBrowser.Controller.Entities
 {
     /// <summary>

+ 2 - 2
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -39,7 +39,7 @@ namespace MediaBrowser.Controller.Entities
             MediaTypes = Array.Empty<string>();
             MinSimilarityScore = 20;
             OfficialRatings = Array.Empty<string>();
-            OrderBy = Array.Empty<(string, SortOrder)>();
+            OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();
             PersonIds = Array.Empty<Guid>();
             PersonTypes = Array.Empty<string>();
             PresetViews = Array.Empty<string>();
@@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.Entities
 
         public bool? HasChapterImages { get; set; }
 
-        public IReadOnlyList<(string OrderBy, SortOrder SortOrder)> OrderBy { get; set; }
+        public IReadOnlyList<(ItemSortBy OrderBy, SortOrder SortOrder)> OrderBy { get; set; }
 
         public DateTime? MinDateCreated { get; set; }
 

+ 4 - 4
MediaBrowser.Controller/Entities/Movies/BoxSet.cs

@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Entities.Movies
     {
         public BoxSet()
         {
-            DisplayOrder = ItemSortBy.PremiereDate;
+            DisplayOrder = "PremiereDate";
         }
 
         [JsonIgnore]
@@ -116,13 +116,13 @@ namespace MediaBrowser.Controller.Entities.Movies
         {
             var children = base.GetChildren(user, includeLinkedChildren, query);
 
-            if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(DisplayOrder, "SortName", StringComparison.OrdinalIgnoreCase))
             {
                 // Sort by name
                 return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
             }
 
-            if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase))
             {
                 // Sort by release date
                 return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();
@@ -136,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Movies
         {
             var children = base.GetRecursiveChildren(user, query);
 
-            if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase))
             {
                 // Sort by release date
                 return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList();

+ 2 - 2
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -199,9 +199,9 @@ namespace MediaBrowser.Controller.Library
         /// <param name="sortBy">The sort by.</param>
         /// <param name="sortOrder">The sort order.</param>
         /// <returns>IEnumerable{BaseItem}.</returns>
-        IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder);
+        IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder);
 
-        IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy);
+        IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy);
 
         /// <summary>
         /// Gets the user root folder.

+ 1 - 0
MediaBrowser.Controller/Providers/EpisodeInfo.cs

@@ -4,6 +4,7 @@
 
 using System;
 using System.Collections.Generic;
+using Jellyfin.Data.Enums;
 
 namespace MediaBrowser.Controller.Providers
 {

+ 3 - 3
MediaBrowser.Controller/Sorting/IBaseItemComparer.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Entities;
 
 namespace MediaBrowser.Controller.Sorting
@@ -9,9 +10,8 @@ namespace MediaBrowser.Controller.Sorting
     public interface IBaseItemComparer : IComparer<BaseItem?>
     {
         /// <summary>
-        /// Gets the name.
+        /// Gets the comparer type.
         /// </summary>
-        /// <value>The name.</value>
-        string Name { get; }
+        ItemSortBy Type { get; }
     }
 }

+ 1 - 0
MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs

@@ -6,6 +6,7 @@ using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Xml;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;

+ 2 - 2
MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Model.LiveTv
         public LiveTvChannelQuery()
         {
             EnableUserData = true;
-            SortBy = Array.Empty<string>();
+            SortBy = Array.Empty<ItemSortBy>();
         }
 
         /// <summary>
@@ -99,7 +99,7 @@ namespace MediaBrowser.Model.LiveTv
 
         public bool? IsSeries { get; set; }
 
-        public string[] SortBy { get; set; }
+        public ItemSortBy[] SortBy { get; set; }
 
         /// <summary>
         /// Gets or sets the sort order to return results with.

+ 0 - 163
MediaBrowser.Model/Querying/ItemSortBy.cs

@@ -1,163 +0,0 @@
-namespace MediaBrowser.Model.Querying
-{
-    /// <summary>
-    /// These represent sort orders that are known by the core.
-    /// </summary>
-    public static class ItemSortBy
-    {
-        /// <summary>
-        /// The aired episode order.
-        /// </summary>
-        public const string AiredEpisodeOrder = "AiredEpisodeOrder";
-
-        /// <summary>
-        /// The album.
-        /// </summary>
-        public const string Album = "Album";
-
-        /// <summary>
-        /// The album artist.
-        /// </summary>
-        public const string AlbumArtist = "AlbumArtist";
-
-        /// <summary>
-        /// The artist.
-        /// </summary>
-        public const string Artist = "Artist";
-
-        /// <summary>
-        /// The date created.
-        /// </summary>
-        public const string DateCreated = "DateCreated";
-
-        /// <summary>
-        /// The official rating.
-        /// </summary>
-        public const string OfficialRating = "OfficialRating";
-
-        /// <summary>
-        /// The date played.
-        /// </summary>
-        public const string DatePlayed = "DatePlayed";
-
-        /// <summary>
-        /// The premiere date.
-        /// </summary>
-        public const string PremiereDate = "PremiereDate";
-
-        /// <summary>
-        /// The start date.
-        /// </summary>
-        public const string StartDate = "StartDate";
-
-        /// <summary>
-        /// The sort name.
-        /// </summary>
-        public const string SortName = "SortName";
-
-        /// <summary>
-        /// The name.
-        /// </summary>
-        public const string Name = "Name";
-
-        /// <summary>
-        /// The random.
-        /// </summary>
-        public const string Random = "Random";
-
-        /// <summary>
-        /// The runtime.
-        /// </summary>
-        public const string Runtime = "Runtime";
-
-        /// <summary>
-        /// The community rating.
-        /// </summary>
-        public const string CommunityRating = "CommunityRating";
-
-        /// <summary>
-        /// The production year.
-        /// </summary>
-        public const string ProductionYear = "ProductionYear";
-
-        /// <summary>
-        /// The play count.
-        /// </summary>
-        public const string PlayCount = "PlayCount";
-
-        /// <summary>
-        /// The critic rating.
-        /// </summary>
-        public const string CriticRating = "CriticRating";
-
-        /// <summary>
-        /// The IsFolder boolean.
-        /// </summary>
-        public const string IsFolder = "IsFolder";
-
-        /// <summary>
-        /// The IsUnplayed boolean.
-        /// </summary>
-        public const string IsUnplayed = "IsUnplayed";
-
-        /// <summary>
-        /// The IsPlayed boolean.
-        /// </summary>
-        public const string IsPlayed = "IsPlayed";
-
-        /// <summary>
-        /// The series sort.
-        /// </summary>
-        public const string SeriesSortName = "SeriesSortName";
-
-        /// <summary>
-        /// The video bitrate.
-        /// </summary>
-        public const string VideoBitRate = "VideoBitRate";
-
-        /// <summary>
-        /// The air time.
-        /// </summary>
-        public const string AirTime = "AirTime";
-
-        /// <summary>
-        /// The studio.
-        /// </summary>
-        public const string Studio = "Studio";
-
-        /// <summary>
-        /// The IsFavouriteOrLiked boolean.
-        /// </summary>
-        public const string IsFavoriteOrLiked = "IsFavoriteOrLiked";
-
-        /// <summary>
-        /// The last content added date.
-        /// </summary>
-        public const string DateLastContentAdded = "DateLastContentAdded";
-
-        /// <summary>
-        /// The series last played date.
-        /// </summary>
-        public const string SeriesDatePlayed = "SeriesDatePlayed";
-
-        /// <summary>
-        /// The parent index number.
-        /// </summary>
-        public const string ParentIndexNumber = "ParentIndexNumber";
-
-        /// <summary>
-        /// The index number.
-        /// </summary>
-        public const string IndexNumber = "IndexNumber";
-
-        /// <summary>
-        /// The similarity score.
-        /// </summary>
-        public const string SimilarityScore = "SimilarityScore";
-
-        /// <summary>
-        /// The search score.
-        /// </summary>
-        public const string SearchScore = "SearchScore";
-    }
-}

+ 1 - 0
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -8,6 +8,7 @@ using System.Linq;
 using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
 using Jellyfin.Extensions;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;

+ 1 - 0
MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Threading;
 using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Providers;

+ 18 - 18
tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs

@@ -14,7 +14,7 @@ namespace Jellyfin.Api.Tests.Helpers
     {
         [Theory]
         [MemberData(nameof(GetOrderBy_Success_TestData))]
-        public static void GetOrderBy_Success(IReadOnlyList<string> sortBy, IReadOnlyList<SortOrder> requestedSortOrder, (string, SortOrder)[] expected)
+        public static void GetOrderBy_Success(IReadOnlyList<ItemSortBy> sortBy, IReadOnlyList<SortOrder> requestedSortOrder, (ItemSortBy, SortOrder)[] expected)
         {
             Assert.Equal(expected, RequestHelpers.GetOrderBy(sortBy, requestedSortOrder));
         }
@@ -95,42 +95,42 @@ namespace Jellyfin.Api.Tests.Helpers
             Assert.Throws<SecurityException>(() => RequestHelpers.GetUserId(principal, requestUserId));
         }
 
-        public static TheoryData<IReadOnlyList<string>, IReadOnlyList<SortOrder>, (string, SortOrder)[]> GetOrderBy_Success_TestData()
+        public static TheoryData<IReadOnlyList<ItemSortBy>, IReadOnlyList<SortOrder>, (ItemSortBy, SortOrder)[]> GetOrderBy_Success_TestData()
         {
-            var data = new TheoryData<IReadOnlyList<string>, IReadOnlyList<SortOrder>, (string, SortOrder)[]>();
+            var data = new TheoryData<IReadOnlyList<ItemSortBy>, IReadOnlyList<SortOrder>, (ItemSortBy, SortOrder)[]>();
 
             data.Add(
-                Array.Empty<string>(),
+                Array.Empty<ItemSortBy>(),
                 Array.Empty<SortOrder>(),
-                Array.Empty<(string, SortOrder)>());
+                Array.Empty<(ItemSortBy, SortOrder)>());
 
             data.Add(
-                new string[]
+                new[]
                 {
-                    "IsFavoriteOrLiked",
-                    "Random"
+                    ItemSortBy.IsFavoriteOrLiked,
+                    ItemSortBy.Random
                 },
                 Array.Empty<SortOrder>(),
-                new (string, SortOrder)[]
+                new (ItemSortBy, SortOrder)[]
                 {
-                    ("IsFavoriteOrLiked", SortOrder.Ascending),
-                    ("Random", SortOrder.Ascending),
+                    (ItemSortBy.IsFavoriteOrLiked, SortOrder.Ascending),
+                    (ItemSortBy.Random, SortOrder.Ascending),
                 });
 
             data.Add(
-                new string[]
+                new[]
                 {
-                    "SortName",
-                    "ProductionYear"
+                    ItemSortBy.SortName,
+                    ItemSortBy.ProductionYear
                 },
-                new SortOrder[]
+                new[]
                 {
                     SortOrder.Descending
                 },
-                new (string, SortOrder)[]
+                new (ItemSortBy, SortOrder)[]
                 {
-                    ("SortName", SortOrder.Descending),
-                    ("ProductionYear", SortOrder.Descending),
+                    (ItemSortBy.SortName, SortOrder.Descending),
+                    (ItemSortBy.ProductionYear, SortOrder.Descending),
                 });
 
             return data;