aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-08-03 10:50:33 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-08-03 10:50:33 +0200
commit4e2089b6a18c323c6c3d158aeba87098ff400450 (patch)
treeb6435cc82d8cfb86fe607a25594ba0cc4d455383 /MediaBrowser.Controller
parent33a8cdfc0b77d7a2439aeb3472db5adda095b41b (diff)
Keep folder extras with the item that owns the folder
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs20
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs19
3 files changed, 38 insertions, 3 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 9c6d18d509..28f40cb7fa 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -771,6 +771,17 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
protected virtual bool SupportsOwnedItems => !ParentId.IsEmpty() && IsFileProtocol;
+ /// <summary>
+ /// Gets a value indicating whether this item searches the folder it lives in for its own extras.
+ /// </summary>
+ [JsonIgnore]
+ protected virtual bool SearchesContainingFolderForExtras =>
+ IsFileProtocol
+ && SupportsOwnedItems
+ && !IsInMixedFolder
+ && this is not (ICollectionFolder or UserRootFolder or AggregateFolder)
+ && GetType() != typeof(Folder);
+
[JsonIgnore]
public virtual bool SupportsPeople => false;
@@ -1528,7 +1539,14 @@ namespace MediaBrowser.Controller.Entities
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
- if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
+ if (!SearchesContainingFolderForExtras)
+ {
+ return false;
+ }
+
+ if (GetParent() is Folder container
+ && container.SearchesContainingFolderForExtras
+ && string.Equals(container.Path, ContainingFolderPath, StringComparison.OrdinalIgnoreCase))
{
return false;
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 42e4f79942..40f917d50c 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities.TV
public int? IndexNumberEnd { get; set; }
[JsonIgnore]
- protected override bool SupportsOwnedItems => IsStacked || MediaSourceCount > 1;
+ protected override bool SupportsOwnedItems => IsStacked || LocalAlternateVersions.Length > 0 || MediaSourceCount > 1;
[JsonIgnore]
public override bool SupportsInheritedParentImages => true;
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 5012378c52..e2f91aa04a 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -527,7 +527,13 @@ namespace MediaBrowser.Controller.Entities
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
- var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
+ var hasChanges = false;
+
+ // The extras of a version group are maintained by its primary.
+ if (!PrimaryVersionId.HasValue)
+ {
+ hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
+ }
// Clean up LocalAlternateVersions - remove paths that no longer exist
if (LocalAlternateVersions.Length > 0)
@@ -588,10 +594,20 @@ namespace MediaBrowser.Controller.Entities
{
altVideo.OwnerId = Id;
altVideo.SetPrimaryVersionId(Id);
+ altVideo.IsInMixedFolder = IsInMixedFolder;
LibraryManager.CreateItem(altVideo, GetParent());
}
}
+ // A version is resolved on its own, so it does not learn whether the folder it sits in
+ // holds other items. It has to share that with the version it belongs to, before the
+ // refresh below acts on it.
+ if (LibraryManager.GetItemById(id) is Video resolvedVersion && resolvedVersion.IsInMixedFolder != IsInMixedFolder)
+ {
+ resolvedVersion.IsInMixedFolder = IsInMixedFolder;
+ await resolvedVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
+ }
+
await RefreshMetadataForOwnedVideo(options, copyTitleMetadata, path, cancellationToken).ConfigureAwait(false);
// Create LinkedChild entry for this local alternate version
@@ -671,6 +687,7 @@ namespace MediaBrowser.Controller.Entities
video.Id = id;
video.OwnerId = Id;
+ video.IsInMixedFolder = IsInMixedFolder;
LibraryManager.CreateItem(video, parentFolder);
newOptions.ForceSave = true;
}