From 24f355a7790ff81359b0cb3bbe98329b6c516866 Mon Sep 17 00:00:00 2001 From: ItsAllAboutTheCode <52703+ItsAllAboutTheCode@users.noreply.github.com> Date: Sun, 21 Jul 2024 14:16:31 +0000 Subject: [PATCH] Changed `GetThemeMedia` to support SortBy/Order options (#12167) * Changed `GetThemeMedia` to support SortBy/Order options The `GetThemeMedia, `GetThemeVideos` and `GetThemeSongs` functions can optionally sort the results based based on passing an ItemSortBy type and a SortOrder. This is intended to be used by jellyfin-web in order to allow users to control the order of theme playback. See PR: https://github.com/jellyfin/jellyfin-web/pull/5714 * Update MediaBrowser.Controller/Entities/BaseItem.cs Fix the `GetThemeVideos` two argument overload having both parameters defaulted. For the two argument overload, both parameters are required. --- Jellyfin.Api/Controllers/LibraryController.cs | 38 +++++++++++++++---- MediaBrowser.Controller/Entities/BaseItem.cs | 18 +++++++-- .../Entities/UserViewBuilder.cs | 4 +- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 64df4c4f04..62cb593351 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -131,6 +131,8 @@ public class LibraryController : BaseJellyfinApiController /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. Determines whether or not parent items should be searched for theme media. + /// Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + /// Optional. Sort Order - Ascending, Descending. /// Theme songs returned. /// Item not found. /// The item theme songs. @@ -141,7 +143,9 @@ public class LibraryController : BaseJellyfinApiController public ActionResult GetThemeSongs( [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, - [FromQuery] bool inheritFromParent = false) + [FromQuery] bool inheritFromParent = false, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[]? sortBy = null, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[]? sortOrder = null) { userId = RequestHelpers.GetUserId(User, userId); var user = userId.IsNullOrEmpty() @@ -158,11 +162,15 @@ public class LibraryController : BaseJellyfinApiController return NotFound(); } + sortOrder ??= []; + sortBy ??= []; + var orderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder); + IReadOnlyList themeItems; while (true) { - themeItems = item.GetThemeSongs(); + themeItems = item.GetThemeSongs(user, orderBy); if (themeItems.Count > 0 || !inheritFromParent) { @@ -197,6 +205,8 @@ public class LibraryController : BaseJellyfinApiController /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. Determines whether or not parent items should be searched for theme media. + /// Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + /// Optional. Sort Order - Ascending, Descending. /// Theme videos returned. /// Item not found. /// The item theme videos. @@ -207,7 +217,9 @@ public class LibraryController : BaseJellyfinApiController public ActionResult GetThemeVideos( [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, - [FromQuery] bool inheritFromParent = false) + [FromQuery] bool inheritFromParent = false, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[]? sortBy = null, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[]? sortOrder = null) { userId = RequestHelpers.GetUserId(User, userId); var user = userId.IsNullOrEmpty() @@ -223,11 +235,15 @@ public class LibraryController : BaseJellyfinApiController return NotFound(); } + sortOrder ??= []; + sortBy ??= []; + var orderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder); + IEnumerable themeItems; while (true) { - themeItems = item.GetThemeVideos(); + themeItems = item.GetThemeVideos(user, orderBy); if (themeItems.Any() || !inheritFromParent) { @@ -262,6 +278,8 @@ public class LibraryController : BaseJellyfinApiController /// The item id. /// Optional. Filter by user id, and attach user data. /// Optional. Determines whether or not parent items should be searched for theme media. + /// Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + /// Optional. Sort Order - Ascending, Descending. /// Theme songs and videos returned. /// Item not found. /// The item theme videos. @@ -271,17 +289,23 @@ public class LibraryController : BaseJellyfinApiController public ActionResult GetThemeMedia( [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, - [FromQuery] bool inheritFromParent = false) + [FromQuery] bool inheritFromParent = false, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[]? sortBy = null, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[]? sortOrder = null) { var themeSongs = GetThemeSongs( itemId, userId, - inheritFromParent); + inheritFromParent, + sortBy, + sortOrder); var themeVideos = GetThemeVideos( itemId, userId, - inheritFromParent); + inheritFromParent, + sortBy, + sortOrder); if (themeSongs.Result is StatusCodeResult { StatusCode: StatusCodes.Status404NotFound } || themeVideos.Result is StatusCodeResult { StatusCode: StatusCodes.Status404NotFound }) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 68ae67d053..7b6f364f7d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2544,14 +2544,24 @@ namespace MediaBrowser.Controller.Entities StringComparison.OrdinalIgnoreCase); } - public IReadOnlyList GetThemeSongs() + public IReadOnlyList GetThemeSongs(User user = null) { - return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeSong).ToArray(); + return GetThemeSongs(user, Array.Empty<(ItemSortBy, SortOrder)>()); } - public IReadOnlyList GetThemeVideos() + public IReadOnlyList GetThemeSongs(User user, IEnumerable<(ItemSortBy SortBy, SortOrder SortOrder)> orderBy) { - return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeVideo).ToArray(); + return LibraryManager.Sort(GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeSong), user, orderBy).ToArray(); + } + + public IReadOnlyList GetThemeVideos(User user = null) + { + return GetThemeVideos(user, Array.Empty<(ItemSortBy, SortOrder)>()); + } + + public IReadOnlyList GetThemeVideos(User user, IEnumerable<(ItemSortBy SortBy, SortOrder SortOrder)> orderBy) + { + return LibraryManager.Sort(GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeVideo), user, orderBy).ToArray(); } /// diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 4af000557e..3a1d0c070b 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -744,7 +744,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeSong.Value; - var themeCount = item.GetThemeSongs().Count; + var themeCount = item.GetThemeSongs(user).Count; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) @@ -757,7 +757,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeVideo.Value; - var themeCount = item.GetThemeVideos().Count; + var themeCount = item.GetThemeVideos(user).Count; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok)