aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Library')
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs63
-rw-r--r--Emby.Server.Implementations/Library/Search/SearchManager.cs38
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs6
3 files changed, 68 insertions, 39 deletions
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 19371f68d7..2bba659a23 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -412,6 +412,13 @@ namespace Emby.Server.Implementations.Library
}
_persistenceService.DeleteItem([.. pathMaps.Select(f => f.Item.Id)]);
+
+ // Evict the deleted items from the cache and announce each removal.
+ foreach (var (item, _, _) in pathMaps)
+ {
+ _cache.TryRemove(item.Id, out _);
+ ReportItemRemoved(item, item.GetOwner() ?? item.GetParent());
+ }
}
public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem)
@@ -611,6 +618,12 @@ namespace Emby.Server.Implementations.Library
folder.UserData = null;
}
+ // Announce the descendants before the item itself.
+ foreach (var child in children)
+ {
+ ReportItemRemoved(child, item);
+ }
+
ReportItemRemoved(item, parent);
}
@@ -1901,14 +1914,14 @@ namespace Emby.Server.Implementations.Library
}
// Optimize by querying against top level views
- query.TopParentIds = parents.SelectMany(i => GetTopParentIdsForQuery(i, query.User)).ToArray();
- query.AncestorIds = [];
-
- // Prevent searching in all libraries due to empty filter
- if (query.TopParentIds.Length == 0)
+ var topParentIds = parents.SelectMany(i => GetTopParentIdsForQuery(i, query.User)).ToArray();
+ if (topParentIds.Length == 0)
{
- query.TopParentIds = [Guid.NewGuid()];
+ return;
}
+
+ query.TopParentIds = topParentIds;
+ query.AncestorIds = [];
}
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query)
@@ -1954,12 +1967,15 @@ namespace Emby.Server.Implementations.Library
if (parents.All(i => i is ICollectionFolder || i is UserView))
{
// Optimize by querying against top level views
- query.TopParentIds = parents.SelectMany(i => GetTopParentIdsForQuery(i, query.User)).ToArray();
+ var topParentIds = parents.SelectMany(i => GetTopParentIdsForQuery(i, query.User)).ToArray();
- // Prevent searching in all libraries due to empty filter
- if (query.TopParentIds.Length == 0)
+ if (topParentIds.Length > 0)
{
- query.TopParentIds = [Guid.NewGuid()];
+ query.TopParentIds = topParentIds;
+ }
+ else
+ {
+ SetAncestorIds(query, parents);
}
}
else if (parents.Count == 1 && parents.First() is Folder folder
@@ -1983,19 +1999,24 @@ namespace Emby.Server.Implementations.Library
}
else
{
- // We need to be able to query from any arbitrary ancestor up the tree
- query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).ToArray();
-
- // Prevent searching in all libraries due to empty filter
- if (query.AncestorIds.Length == 0)
- {
- query.AncestorIds = [Guid.NewGuid()];
- }
+ SetAncestorIds(query, parents);
}
query.Parent = null;
}
+ private static void SetAncestorIds(InternalItemsQuery query, IReadOnlyCollection<BaseItem> parents)
+ {
+ // We need to be able to query from any arbitrary ancestor up the tree
+ query.AncestorIds = parents.SelectMany(i => i.GetIdsForAncestorQuery()).ToArray();
+
+ // Prevent searching in all libraries due to empty filter
+ if (query.AncestorIds.Length == 0)
+ {
+ query.AncestorIds = [Guid.NewGuid()];
+ }
+ }
+
private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExternalContent = true)
{
if (query.User is null)
@@ -2235,6 +2256,12 @@ namespace Emby.Server.Implementations.Library
}
/// <inheritdoc />
+ public IReadOnlySet<Guid> GetItemIdsWithAlternateVersions(IReadOnlyList<Guid> itemIds)
+ {
+ return _linkedChildrenService.GetItemIdsWithAlternateVersions(itemIds);
+ }
+
+ /// <inheritdoc />
public void UpsertLinkedChild(Guid parentId, Guid childId, MediaBrowser.Controller.Entities.LinkedChildType childType)
{
_linkedChildrenService.UpsertLinkedChild(parentId, childId, childType);
diff --git a/Emby.Server.Implementations/Library/Search/SearchManager.cs b/Emby.Server.Implementations/Library/Search/SearchManager.cs
index 01f9062734..0e180753a6 100644
--- a/Emby.Server.Implementations/Library/Search/SearchManager.cs
+++ b/Emby.Server.Implementations/Library/Search/SearchManager.cs
@@ -92,37 +92,33 @@ public class SearchManager : ISearchManager
await Task.WhenAll(externalTask, internalTask).ConfigureAwait(false);
var externalResults = await externalTask.ConfigureAwait(false);
- var fromExternal = externalResults.Count > 0;
- IReadOnlyList<SearchResult> results;
- if (fromExternal)
- {
- results = externalResults;
- }
- else
- {
- results = await internalTask.ConfigureAwait(false);
- if (_internalProviders.Length > 0)
- {
- _logger.LogDebug("No results from external providers, using internal provider results");
- }
- }
// Internal providers apply user-access filtering inline in their queries. External
// providers don't know about user permissions, so they may return IDs from hidden
- // libraries or items the user is otherwise blocked from. Run the post-filter only
- // when results came from externals to close that gap. The Items controller's second
- // roundtrip via folder.GetItems applies most of these again, but it does not restrict
- // by TopParentIds when ItemIds is set.
- if (fromExternal && results.Count > 0 && query.UserId.HasValue && !query.UserId.Value.IsEmpty())
+ // libraries or items the user is otherwise blocked from. Filter them here to close
+ // that gap. The Items controller's second roundtrip via folder.GetItems applies most
+ // of these again, but it does not restrict by TopParentIds when ItemIds is set.
+ if (externalResults.Count > 0 && query.UserId.HasValue && !query.UserId.Value.IsEmpty())
{
var user = _userManager.GetUserById(query.UserId.Value);
if (user is not null)
{
- results = await FilterByUserAccessAsync(results, user, query, cancellationToken).ConfigureAwait(false);
+ externalResults = await FilterByUserAccessAsync(externalResults, user, query, cancellationToken).ConfigureAwait(false);
}
}
- return results;
+ if (externalResults.Count > 0)
+ {
+ return externalResults;
+ }
+
+ var internalResults = await internalTask.ConfigureAwait(false);
+ if (_internalProviders.Length > 0)
+ {
+ _logger.LogDebug("No results from external providers, using internal provider results");
+ }
+
+ return internalResults;
}
private async Task<IReadOnlyList<SearchResult>> FilterByUserAccessAsync(
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index 9512b0ffd7..49d76e195d 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -396,6 +396,12 @@ namespace Emby.Server.Implementations.Library
query.Limit = limit;
return _libraryManager.GetLatestItemList(query, parents, CollectionType.movies);
}
+
+ if (collectionType is null)
+ {
+ query.Limit = limit;
+ return _libraryManager.GetLatestItemList(query, parents, CollectionType.unknown);
+ }
}
return _libraryManager.GetItemList(query, parents);