|
@@ -28,6 +28,9 @@ namespace MediaBrowser.Controller.Entities
|
|
public List<Guid> ThemeSongIds { get; set; }
|
|
public List<Guid> ThemeSongIds { get; set; }
|
|
public List<Guid> ThemeVideoIds { get; set; }
|
|
public List<Guid> ThemeVideoIds { get; set; }
|
|
|
|
|
|
|
|
+ [IgnoreDataMember]
|
|
|
|
+ public DateTime? DateLastMediaAdded { get; set; }
|
|
|
|
+
|
|
public Folder()
|
|
public Folder()
|
|
{
|
|
{
|
|
LinkedChildren = new List<LinkedChild>();
|
|
LinkedChildren = new List<LinkedChild>();
|
|
@@ -55,6 +58,36 @@ namespace MediaBrowser.Controller.Entities
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ [IgnoreDataMember]
|
|
|
|
+ public virtual bool SupportsCumulativeRunTimeTicks
|
|
|
|
+ {
|
|
|
|
+ get
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ [IgnoreDataMember]
|
|
|
|
+ public virtual bool SupportsDateLastMediaAdded
|
|
|
|
+ {
|
|
|
|
+ get
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override bool RequiresRefresh()
|
|
|
|
+ {
|
|
|
|
+ var baseResult = base.RequiresRefresh();
|
|
|
|
+
|
|
|
|
+ if (SupportsCumulativeRunTimeTicks && !RunTimeTicks.HasValue)
|
|
|
|
+ {
|
|
|
|
+ baseResult = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return baseResult;
|
|
|
|
+ }
|
|
|
|
+
|
|
[IgnoreDataMember]
|
|
[IgnoreDataMember]
|
|
public override string FileNameWithoutExtension
|
|
public override string FileNameWithoutExtension
|
|
{
|
|
{
|
|
@@ -199,8 +232,8 @@ namespace MediaBrowser.Controller.Entities
|
|
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
|
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
|
protected virtual IEnumerable<string> GetIndexByOptions()
|
|
protected virtual IEnumerable<string> GetIndexByOptions()
|
|
{
|
|
{
|
|
- return new List<string> {
|
|
|
|
- {"None"},
|
|
|
|
|
|
+ return new List<string> {
|
|
|
|
+ {"None"},
|
|
{"Performer"},
|
|
{"Performer"},
|
|
{"Genre"},
|
|
{"Genre"},
|
|
{"Director"},
|
|
{"Director"},
|
|
@@ -707,8 +740,8 @@ namespace MediaBrowser.Controller.Entities
|
|
{
|
|
{
|
|
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
|
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
|
{
|
|
{
|
|
- ParentId = Id
|
|
|
|
-
|
|
|
|
|
|
+ ParentId = Id,
|
|
|
|
+ GroupByPresentationUniqueKey = false
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
@@ -751,39 +784,44 @@ namespace MediaBrowser.Controller.Entities
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
|
|
|
|
|
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
|
{
|
|
{
|
|
- if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
|
+ if (!supportsUserDataQueries)
|
|
{
|
|
{
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
|
|
|
- return true;
|
|
|
|
|
|
+ if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
- if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
|
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
|
@@ -799,11 +837,6 @@ namespace MediaBrowser.Controller.Entities
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
- if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
|
|
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
|
|
@@ -819,11 +852,6 @@ namespace MediaBrowser.Controller.Entities
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
- if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
|
@@ -839,11 +867,6 @@ namespace MediaBrowser.Controller.Entities
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
- if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
|
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
|
@@ -868,34 +891,37 @@ namespace MediaBrowser.Controller.Entities
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (query.IsLiked.HasValue)
|
|
|
|
|
|
+ if (!supportsUserDataQueries)
|
|
{
|
|
{
|
|
- Logger.Debug("Query requires post-filtering due to IsLiked");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (query.IsLiked.HasValue)
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to IsLiked");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- if (query.IsFavoriteOrLiked.HasValue)
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (query.IsFavoriteOrLiked.HasValue)
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- if (query.IsFavorite.HasValue)
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to IsFavorite");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (query.IsFavorite.HasValue)
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to IsFavorite");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- if (query.IsResumable.HasValue)
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to IsResumable");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (query.IsResumable.HasValue)
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to IsResumable");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
- if (query.IsPlayed.HasValue)
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to IsPlayed");
|
|
|
|
- return true;
|
|
|
|
|
|
+ if (query.IsPlayed.HasValue)
|
|
|
|
+ {
|
|
|
|
+ Logger.Debug("Query requires post-filtering due to IsPlayed");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (query.IsInBoxSet.HasValue)
|
|
if (query.IsInBoxSet.HasValue)
|
|
@@ -1059,30 +1085,6 @@ namespace MediaBrowser.Controller.Entities
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!string.IsNullOrWhiteSpace(query.NameContains))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to NameContains");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!string.IsNullOrWhiteSpace(query.NameLessThan))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to NameLessThan");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to NameStartsWith");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (query.AirDays.Length > 0)
|
|
if (query.AirDays.Length > 0)
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to AirDays");
|
|
Logger.Debug("Query requires post-filtering due to AirDays");
|
|
@@ -1107,12 +1109,6 @@ namespace MediaBrowser.Controller.Entities
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (query.AlbumNames.Length > 0)
|
|
|
|
- {
|
|
|
|
- Logger.Debug("Query requires post-filtering due to AlbumNames");
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (query.ArtistNames.Length > 0)
|
|
if (query.ArtistNames.Length > 0)
|
|
{
|
|
{
|
|
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
|
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
|
@@ -1297,33 +1293,42 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
|
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
|
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
|
{
|
|
{
|
|
- var list = new List<BaseItem>();
|
|
|
|
|
|
+ var result = new Dictionary<Guid, BaseItem>();
|
|
|
|
|
|
- AddChildrenToList(list, true, filter);
|
|
|
|
|
|
+ AddChildrenToList(result, true, true, filter);
|
|
|
|
|
|
- return list;
|
|
|
|
|
|
+ return result.Values.ToList();
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Adds the children to list.
|
|
/// Adds the children to list.
|
|
/// </summary>
|
|
/// </summary>
|
|
- /// <param name="list">The list.</param>
|
|
|
|
- /// <param name="recursive">if set to <c>true</c> [recursive].</param>
|
|
|
|
- /// <param name="filter">The filter.</param>
|
|
|
|
- private void AddChildrenToList(List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
|
|
|
|
|
|
+ private void AddChildrenToList(Dictionary<Guid,BaseItem> result, bool includeLinkedChildren, bool recursive, Func<BaseItem, bool> filter)
|
|
{
|
|
{
|
|
foreach (var child in Children)
|
|
foreach (var child in Children)
|
|
{
|
|
{
|
|
if (filter == null || filter(child))
|
|
if (filter == null || filter(child))
|
|
{
|
|
{
|
|
- list.Add(child);
|
|
|
|
|
|
+ result[child.Id] = child;
|
|
}
|
|
}
|
|
|
|
|
|
if (recursive && child.IsFolder)
|
|
if (recursive && child.IsFolder)
|
|
{
|
|
{
|
|
var folder = (Folder)child;
|
|
var folder = (Folder)child;
|
|
|
|
|
|
- folder.AddChildrenToList(list, true, filter);
|
|
|
|
|
|
+ // We can only support includeLinkedChildren for the first folder, or we might end up stuck in a loop of linked items
|
|
|
|
+ folder.AddChildrenToList(result, false, true, filter);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (includeLinkedChildren)
|
|
|
|
+ {
|
|
|
|
+ foreach (var child in GetLinkedChildren())
|
|
|
|
+ {
|
|
|
|
+ if (filter == null || filter(child))
|
|
|
|
+ {
|
|
|
|
+ result[child.Id] = child;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1567,38 +1572,17 @@ namespace MediaBrowser.Controller.Entities
|
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
|
- /// Finds an item by path, recursively
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="path">The path.</param>
|
|
|
|
- /// <returns>BaseItem.</returns>
|
|
|
|
- /// <exception cref="System.ArgumentNullException"></exception>
|
|
|
|
- public BaseItem FindByPath(string path)
|
|
|
|
|
|
+ public override bool IsPlayed(User user)
|
|
{
|
|
{
|
|
- if (string.IsNullOrEmpty(path))
|
|
|
|
|
|
+ var itemsResult = GetItems(new InternalItemsQuery(user)
|
|
{
|
|
{
|
|
- throw new ArgumentNullException();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (string.Equals(Path, path, StringComparison.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ Recursive = true,
|
|
|
|
+ IsFolder = false,
|
|
|
|
+ ExcludeLocationTypes = new[] { LocationType.Virtual }
|
|
|
|
|
|
- return GetRecursiveChildren(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
- (!i.IsFolder && !i.IsInMixedFolder && string.Equals(i.ContainingFolderPath, path, StringComparison.OrdinalIgnoreCase)) ||
|
|
|
|
- i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
|
|
|
|
- .FirstOrDefault();
|
|
|
|
- }
|
|
|
|
|
|
+ }).Result;
|
|
|
|
|
|
- public override bool IsPlayed(User user)
|
|
|
|
- {
|
|
|
|
- return GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual)
|
|
|
|
|
|
+ return itemsResult.Items
|
|
.All(i => i.IsPlayed(user));
|
|
.All(i => i.IsPlayed(user));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1607,26 +1591,50 @@ namespace MediaBrowser.Controller.Entities
|
|
return !IsPlayed(user);
|
|
return !IsPlayed(user);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ [IgnoreDataMember]
|
|
|
|
+ public virtual bool SupportsUserDataFromChildren
|
|
|
|
+ {
|
|
|
|
+ get
|
|
|
|
+ {
|
|
|
|
+ // These are just far too slow.
|
|
|
|
+ if (this is ICollectionFolder)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (this is UserView)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (this is UserRootFolder)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
|
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
|
{
|
|
{
|
|
|
|
+ if (!SupportsUserDataFromChildren)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
var recursiveItemCount = 0;
|
|
var recursiveItemCount = 0;
|
|
var unplayed = 0;
|
|
var unplayed = 0;
|
|
|
|
|
|
double totalPercentPlayed = 0;
|
|
double totalPercentPlayed = 0;
|
|
|
|
|
|
- IEnumerable<BaseItem> children;
|
|
|
|
- var folder = this;
|
|
|
|
|
|
+ var itemsResult = GetItems(new InternalItemsQuery(user)
|
|
|
|
+ {
|
|
|
|
+ Recursive = true,
|
|
|
|
+ IsFolder = false,
|
|
|
|
+ ExcludeLocationTypes = new[] { LocationType.Virtual }
|
|
|
|
|
|
- var season = folder as Season;
|
|
|
|
|
|
+ }).Result;
|
|
|
|
|
|
- if (season != null)
|
|
|
|
- {
|
|
|
|
- children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual);
|
|
|
|
- }
|
|
|
|
|
|
+ var children = itemsResult.Items;
|
|
|
|
|
|
// Loop through each recursive child
|
|
// Loop through each recursive child
|
|
foreach (var child in children)
|
|
foreach (var child in children)
|
|
@@ -1635,7 +1643,7 @@ namespace MediaBrowser.Controller.Entities
|
|
|
|
|
|
var isUnplayed = true;
|
|
var isUnplayed = true;
|
|
|
|
|
|
- var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
|
|
|
|
|
|
+ var itemUserData = UserDataManager.GetUserData(user, child);
|
|
|
|
|
|
// Incrememt totalPercentPlayed
|
|
// Incrememt totalPercentPlayed
|
|
if (itemUserData != null)
|
|
if (itemUserData != null)
|