aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-05-20 11:34:45 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-05-20 11:34:45 +0200
commit9dfcc0918f797a0937b688426232e17898648f94 (patch)
tree4d1944c7167183b3d86561adfa7111281a0cd7d7
parent2b2db769483be9b0ddf1982daacd9cac56a05d5a (diff)
Add support for filtering boxsets by parentId
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs8
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.TranslateQuery.cs9
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs7
3 files changed, 24 insertions, 0 deletions
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 43e4737694..f3f0bd2482 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -280,10 +280,17 @@ public class ItemsController : BaseJellyfinApiController
var item = _libraryManager.GetParentItem(parentId, userId);
QueryResult<BaseItem> result;
+ Guid[] boxSetLinkedChildAncestorIds = [];
if (includeItemTypes.Length == 1
&& includeItemTypes[0] == BaseItemKind.BoxSet
&& item is not BoxSet)
{
+ var isBoxSetsLibrary = item is IHasCollectionType hct && hct.CollectionType == CollectionType.boxsets;
+ if (parentId.HasValue && item is not UserRootFolder && !isBoxSetsLibrary)
+ {
+ boxSetLinkedChildAncestorIds = [parentId.Value];
+ }
+
parentId = null;
item = _libraryManager.GetUserRootFolder();
}
@@ -405,6 +412,7 @@ public class ItemsController : BaseJellyfinApiController
MaxPremiereDate = maxPremiereDate?.ToUniversalTime(),
AudioLanguages = audioLanguages,
SubtitleLanguages = subtitleLanguages,
+ LinkedChildAncestorIds = boxSetLinkedChildAncestorIds,
};
if (ids.Length != 0 || !string.IsNullOrWhiteSpace(searchTerm))
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.TranslateQuery.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.TranslateQuery.cs
index 624b1b561c..f33a65a703 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.TranslateQuery.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.TranslateQuery.cs
@@ -1027,6 +1027,15 @@ public sealed partial class BaseItemRepository
baseQuery = baseQuery.Where(e => e.Parents!.AsQueryable().Any(ancestorFilter));
}
+ if (filter.LinkedChildAncestorIds.Length > 0)
+ {
+ // Keep folder-like items (BoxSets, Playlists) whose linked children descend from any of the requested ancestor ids.
+ var linkedChildAncestorIds = filter.LinkedChildAncestorIds;
+ baseQuery = baseQuery.Where(e => context.LinkedChildren.Any(lc =>
+ lc.ParentId == e.Id
+ && lc.Child!.Parents!.Any(a => linkedChildAncestorIds.Contains(a.ParentItemId))));
+ }
+
if (!string.IsNullOrWhiteSpace(filter.AncestorWithPresentationUniqueKey))
{
baseQuery = baseQuery
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 1e5b5aa164..422c40ce5d 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -21,6 +21,7 @@ namespace MediaBrowser.Controller.Entities
AlbumArtistIds = [];
AlbumIds = [];
AncestorIds = [];
+ LinkedChildAncestorIds = [];
ArtistIds = [];
BlockUnratedItems = [];
BoxSetLibraryFolders = [];
@@ -265,6 +266,12 @@ namespace MediaBrowser.Controller.Entities
public Guid[] AncestorIds { get; set; }
+ /// <summary>
+ /// Gets or sets a list of ancestor ids that the item's linked children must descend from.
+ /// Useful for filtering BoxSets/Playlists to only those that contain items from a specific library.
+ /// </summary>
+ public Guid[] LinkedChildAncestorIds { get; set; }
+
public Guid[] TopParentIds { get; set; }
public CollectionType?[] PresetViews { get; set; }