From bb6c3b4eecee46a0a6222ffe17657cabc7da97f4 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Sat, 7 Feb 2026 21:17:01 +0100 Subject: Fix BoxSet collapse handling and deletion --- .../Entities/CollectionFolder.cs | 17 +++++++++++-- MediaBrowser.Controller/Entities/Folder.cs | 28 ++++++++++++++++++++++ .../Entities/InternalItemsQuery.cs | 6 +++++ 3 files changed, 49 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index cf615788ee..ffdc8421da 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -79,14 +79,27 @@ namespace MediaBrowser.Controller.Entities public CollectionType? CollectionType { get; set; } /// - /// Gets the item's children. + /// Gets or sets the item's children. /// /// /// Our children are actually just references to the ones in the physical root... + /// Setting to null propagates invalidation to physical folders since the getter + /// always delegates to and never reads the backing field. /// /// The actual children. [JsonIgnore] - public override IEnumerable Children => GetActualChildren(); + public override IEnumerable Children + { + get => GetActualChildren(); + set + { + // The getter delegates to physical folders, so invalidate their caches. + foreach (var folder in GetPhysicalFolders(true)) + { + folder.Children = null; + } + } + } [JsonIgnore] public override bool SupportsPeople => false; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 44903fd4c1..0c0558b4c1 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -733,6 +733,7 @@ namespace MediaBrowser.Controller.Entities if (!query.ForceDirect && RequiresPostFiltering(query)) { query.CollapseBoxSetItems = true; + SetCollapseBoxSetItemTypes(query); } if (this is not UserRootFolder @@ -1039,6 +1040,33 @@ namespace MediaBrowser.Controller.Entities return (queryHasMovies || queryHasSeries) && AllowBoxSetCollapsing(query); } + private void SetCollapseBoxSetItemTypes(InternalItemsQuery query) + { + var config = ConfigurationManager.Configuration; + bool collapseMovies = config.EnableGroupingMoviesIntoCollections; + bool collapseSeries = config.EnableGroupingShowsIntoCollections; + + if (collapseMovies && collapseSeries) + { + // Empty means collapse all types + query.CollapseBoxSetItemTypes = []; + return; + } + + var types = new List(); + if (collapseMovies) + { + types.Add(BaseItemKind.Movie); + } + + if (collapseSeries) + { + types.Add(BaseItemKind.Series); + } + + query.CollapseBoxSetItemTypes = types.ToArray(); + } + private static bool AllowBoxSetCollapsing(InternalItemsQuery request) { if (request.IsFavorite.HasValue) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index b36ea627d8..2824fb6954 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -113,6 +113,12 @@ namespace MediaBrowser.Controller.Entities public bool? CollapseBoxSetItems { get; set; } + /// + /// Gets or sets the item types that should be collapsed into box sets. + /// When empty, all types are collapsed. When set, only items of these types are replaced by their parent box set. + /// + public BaseItemKind[] CollapseBoxSetItemTypes { get; set; } = []; + public string? NameStartsWithOrGreater { get; set; } public string? NameStartsWith { get; set; } -- cgit v1.2.3