mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
deprecated IndexFolder.cs
This commit is contained in:
parent
50ea8cd941
commit
5f9b99c960
@ -85,7 +85,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
{
|
{
|
||||||
allTypes = allTypes.Where(t =>
|
allTypes = allTypes.Where(t =>
|
||||||
{
|
{
|
||||||
if (t == typeof(UserRootFolder) || t == typeof(AggregateFolder) || t == typeof(Folder) || t == typeof(IndexFolder) || t == typeof(CollectionFolder) || t == typeof(Year))
|
if (t == typeof(UserRootFolder) || t == typeof(AggregateFolder) || t == typeof(Folder) || t == typeof(CollectionFolder) || t == typeof(Year))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -52,12 +52,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
[ApiMember(Name = "SearchTerm", Description = "Optional. If specified, results will be filtered based on a search term.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "SearchTerm", Description = "Optional. If specified, results will be filtered based on a search term.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||||
public string SearchTerm { get; set; }
|
public string SearchTerm { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The dynamic, localized index function name
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The index by.</value>
|
|
||||||
public string IndexBy { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Limit results to items containing specific genres
|
/// Limit results to items containing specific genres
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -358,7 +352,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
items = ((Folder)item).GetChildren(user, true, request.IndexBy);
|
items = ((Folder)item).GetChildren(user, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IncludeIndexContainers)
|
if (request.IncludeIndexContainers)
|
||||||
|
@ -58,13 +58,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
|
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
|
||||||
{
|
{
|
||||||
//we don't directly validate our children
|
|
||||||
//but we do need to clear out the index cache...
|
|
||||||
if (IndexCache != null)
|
|
||||||
{
|
|
||||||
IndexCache.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResetDynamicChildren();
|
ResetDynamicChildren();
|
||||||
|
|
||||||
return NullTaskResult;
|
return NullTaskResult;
|
||||||
|
@ -208,284 +208,25 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
#region Indexing
|
#region Indexing
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The _index by options
|
|
||||||
/// </summary>
|
|
||||||
private Dictionary<string, Func<User, IEnumerable<BaseItem>>> _indexByOptions;
|
|
||||||
/// <summary>
|
|
||||||
/// Dictionary of index options - consists of a display value and an indexing function
|
|
||||||
/// which takes User as a parameter and returns an IEnum of BaseItem
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The index by options.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public Dictionary<string, Func<User, IEnumerable<BaseItem>>> IndexByOptions
|
|
||||||
{
|
|
||||||
get { return _indexByOptions ?? (_indexByOptions = GetIndexByOptions()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the valid set of index by options for this folder type.
|
/// Returns the valid set of index by options for this folder type.
|
||||||
/// Override or extend to modify.
|
/// Override or extend to modify.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
||||||
protected virtual Dictionary<string, Func<User, IEnumerable<BaseItem>>> GetIndexByOptions()
|
protected virtual IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new Dictionary<string, Func<User, IEnumerable<BaseItem>>> {
|
return new List<string> {
|
||||||
{LocalizedStrings.Instance.GetString("NoneDispPref"), null},
|
{LocalizedStrings.Instance.GetString("NoneDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("PerformerDispPref"), GetIndexByPerformer},
|
{LocalizedStrings.Instance.GetString("PerformerDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("GenreDispPref"), GetIndexByGenre},
|
{LocalizedStrings.Instance.GetString("GenreDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("DirectorDispPref"), GetIndexByDirector},
|
{LocalizedStrings.Instance.GetString("DirectorDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("YearDispPref"), GetIndexByYear},
|
{LocalizedStrings.Instance.GetString("YearDispPref")},
|
||||||
//{LocalizedStrings.Instance.GetString("OfficialRatingDispPref"), null},
|
//{LocalizedStrings.Instance.GetString("OfficialRatingDispPref"), null},
|
||||||
{LocalizedStrings.Instance.GetString("StudioDispPref"), GetIndexByStudio}
|
{LocalizedStrings.Instance.GetString("StudioDispPref")}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by actor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GetIndexByPerformer(User user)
|
|
||||||
{
|
|
||||||
return GetIndexByPerson(user, new List<string> { PersonType.Actor, PersonType.GuestStar }, true, LocalizedStrings.Instance.GetString("PerformerDispPref"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by director.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GetIndexByDirector(User user)
|
|
||||||
{
|
|
||||||
return GetIndexByPerson(user, new List<string> { PersonType.Director }, false, LocalizedStrings.Instance.GetString("DirectorDispPref"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by person.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <param name="personTypes">The person types we should match on</param>
|
|
||||||
/// <param name="includeAudio">if set to <c>true</c> [include audio].</param>
|
|
||||||
/// <param name="indexName">Name of the index.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
private IEnumerable<BaseItem> GetIndexByPerson(User user, List<string> personTypes, bool includeAudio, string indexName)
|
|
||||||
{
|
|
||||||
// Even though this implementation means multiple iterations over the target list - it allows us to defer
|
|
||||||
// the retrieval of the individual children for each index value until they are requested.
|
|
||||||
using (new Profiler(indexName + " Index Build for " + Name, Logger))
|
|
||||||
{
|
|
||||||
// Put this in a local variable to avoid an implicitly captured closure
|
|
||||||
var currentIndexName = indexName;
|
|
||||||
|
|
||||||
var us = this;
|
|
||||||
var recursiveChildren = GetRecursiveChildren(user).Where(i => i.IncludeInIndex).ToList();
|
|
||||||
|
|
||||||
// Get the candidates, but handle audio separately
|
|
||||||
var candidates = recursiveChildren.Where(i => i.AllPeople != null && !(i is Audio.Audio)).ToList();
|
|
||||||
|
|
||||||
var indexFolders = candidates.AsParallel().SelectMany(i => i.AllPeople.Where(p => personTypes.Contains(p.Type))
|
|
||||||
.Select(a => a.Name))
|
|
||||||
.Distinct()
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetPerson(i);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting person {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (AggregateException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting person {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.Select(a => new IndexFolder(us, a,
|
|
||||||
candidates.Where(i => i.AllPeople.Any(p => personTypes.Contains(p.Type) && p.Name.Equals(a.Name, StringComparison.OrdinalIgnoreCase))
|
|
||||||
), currentIndexName)).AsEnumerable();
|
|
||||||
|
|
||||||
if (includeAudio)
|
|
||||||
{
|
|
||||||
var songs = recursiveChildren.OfType<Audio.Audio>().ToList();
|
|
||||||
|
|
||||||
indexFolders = songs.SelectMany(i => i.Artists)
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetArtist(i);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting artist {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (AggregateException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting artist {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.Select(a => new IndexFolder(us, a,
|
|
||||||
songs.Where(i => i.Artists.Contains(a.Name, StringComparer.OrdinalIgnoreCase)
|
|
||||||
), currentIndexName)).Concat(indexFolders);
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexFolders;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by studio.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GetIndexByStudio(User user)
|
|
||||||
{
|
|
||||||
// Even though this implementation means multiple iterations over the target list - it allows us to defer
|
|
||||||
// the retrieval of the individual children for each index value until they are requested.
|
|
||||||
using (new Profiler("Studio Index Build for " + Name, Logger))
|
|
||||||
{
|
|
||||||
var indexName = LocalizedStrings.Instance.GetString("StudioDispPref");
|
|
||||||
|
|
||||||
var candidates = GetRecursiveChildren(user).Where(i => i.IncludeInIndex).ToList();
|
|
||||||
|
|
||||||
return candidates.AsParallel().SelectMany(i => i.AllStudios)
|
|
||||||
.Distinct()
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetStudio(i);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting studio {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (AggregateException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting studio {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.Select(ndx => new IndexFolder(this, ndx, candidates.Where(i => i.AllStudios.Any(s => s.Equals(ndx.Name, StringComparison.OrdinalIgnoreCase))), indexName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by genre.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GetIndexByGenre(User user)
|
|
||||||
{
|
|
||||||
// Even though this implementation means multiple iterations over the target list - it allows us to defer
|
|
||||||
// the retrieval of the individual children for each index value until they are requested.
|
|
||||||
using (new Profiler("Genre Index Build for " + Name, Logger))
|
|
||||||
{
|
|
||||||
var indexName = LocalizedStrings.Instance.GetString("GenreDispPref");
|
|
||||||
|
|
||||||
//we need a copy of this so we don't double-recurse
|
|
||||||
var candidates = GetRecursiveChildren(user).Where(i => i.IncludeInIndex).ToList();
|
|
||||||
|
|
||||||
return candidates.AsParallel().SelectMany(i => i.AllGenres)
|
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetGenre(i);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting genre {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
.Select(genre => new IndexFolder(this, genre, candidates.Where(i => i.AllGenres.Any(g => g.Equals(genre.Name, StringComparison.OrdinalIgnoreCase))), indexName)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index by year.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GetIndexByYear(User user)
|
|
||||||
{
|
|
||||||
// Even though this implementation means multiple iterations over the target list - it allows us to defer
|
|
||||||
// the retrieval of the individual children for each index value until they are requested.
|
|
||||||
using (new Profiler("Production Year Index Build for " + Name, Logger))
|
|
||||||
{
|
|
||||||
var indexName = LocalizedStrings.Instance.GetString("YearDispPref");
|
|
||||||
|
|
||||||
//we need a copy of this so we don't double-recurse
|
|
||||||
var candidates = GetRecursiveChildren(user).Where(i => i.IncludeInIndex && i.ProductionYear.HasValue).ToList();
|
|
||||||
|
|
||||||
return candidates.AsParallel().Select(i => i.ProductionYear.Value)
|
|
||||||
.Distinct()
|
|
||||||
.Select(i =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return LibraryManager.GetYear(i);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting year {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (AggregateException ex)
|
|
||||||
{
|
|
||||||
Logger.ErrorException("Error getting year {0}", ex, i);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Where(i => i != null)
|
|
||||||
|
|
||||||
.Select(ndx => new IndexFolder(this, ndx, candidates.Where(i => i.ProductionYear == int.Parse(ndx.Name)), indexName));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the indexed children for this user from the cache. Caches them if not already there.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <param name="indexBy">The index by.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
private IEnumerable<BaseItem> GetIndexedChildren(User user, string indexBy)
|
|
||||||
{
|
|
||||||
List<BaseItem> result = null;
|
|
||||||
var cacheKey = user.Name + indexBy;
|
|
||||||
|
|
||||||
if (IndexCache != null)
|
|
||||||
{
|
|
||||||
IndexCache.TryGetValue(cacheKey, out result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null)
|
|
||||||
{
|
|
||||||
//not cached - cache it
|
|
||||||
Func<User, IEnumerable<BaseItem>> indexing;
|
|
||||||
IndexByOptions.TryGetValue(indexBy, out indexing);
|
|
||||||
result = BuildIndex(indexBy, indexing, user);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the list of indexy by choices for this folder (localized).
|
/// Get the list of indexy by choices for this folder (localized).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -493,31 +234,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public IEnumerable<string> IndexByOptionStrings
|
public IEnumerable<string> IndexByOptionStrings
|
||||||
{
|
{
|
||||||
get { return IndexByOptions.Keys; }
|
get { return GetIndexByOptions(); }
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The index cache
|
|
||||||
/// </summary>
|
|
||||||
protected ConcurrentDictionary<string, List<BaseItem>> IndexCache;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Builds the index.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="indexKey">The index key.</param>
|
|
||||||
/// <param name="indexFunction">The index function.</param>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>List{BaseItem}.</returns>
|
|
||||||
protected virtual List<BaseItem> BuildIndex(string indexKey, Func<User, IEnumerable<BaseItem>> indexFunction, User user)
|
|
||||||
{
|
|
||||||
if (IndexCache == null)
|
|
||||||
{
|
|
||||||
IndexCache = new ConcurrentDictionary<string, List<BaseItem>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexFunction != null
|
|
||||||
? IndexCache[user.Name + indexKey] = indexFunction(user).ToList()
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -765,12 +482,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
AddChildrenInternal(newItems);
|
AddChildrenInternal(newItems);
|
||||||
|
|
||||||
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
//force the indexes to rebuild next time
|
|
||||||
if (IndexCache != null)
|
|
||||||
{
|
|
||||||
IndexCache.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(10);
|
progress.Report(10);
|
||||||
@ -988,10 +699,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
|
||||||
/// <param name="indexBy">The index by.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
/// <exception cref="System.ArgumentNullException"></exception>
|
/// <exception cref="System.ArgumentNullException"></exception>
|
||||||
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null)
|
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
@ -999,19 +709,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
//the true root should return our users root folder children
|
//the true root should return our users root folder children
|
||||||
if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren, indexBy);
|
if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren);
|
||||||
|
|
||||||
IEnumerable<BaseItem> result = null;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(indexBy))
|
|
||||||
{
|
|
||||||
result = GetIndexedChildren(user, indexBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var list = new List<BaseItem>();
|
var list = new List<BaseItem>();
|
||||||
|
|
||||||
|
@ -1,206 +0,0 @@
|
|||||||
using MediaBrowser.Common.Extensions;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using MoreLinq;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class IndexFolder
|
|
||||||
/// </summary>
|
|
||||||
public class IndexFolder : Folder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="IndexFolder" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parent">The parent.</param>
|
|
||||||
/// <param name="shadow">The shadow.</param>
|
|
||||||
/// <param name="children">The children.</param>
|
|
||||||
/// <param name="indexName">Name of the index.</param>
|
|
||||||
/// <param name="groupContents">if set to <c>true</c> [group contents].</param>
|
|
||||||
public IndexFolder(Folder parent, BaseItem shadow, IEnumerable<BaseItem> children, string indexName, bool groupContents = true)
|
|
||||||
{
|
|
||||||
ChildSource = children;
|
|
||||||
ShadowItem = shadow;
|
|
||||||
GroupContents = groupContents;
|
|
||||||
if (shadow == null)
|
|
||||||
{
|
|
||||||
Name = ForcedSortName = "<Unknown>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetShadowValues();
|
|
||||||
}
|
|
||||||
Id = (parent.Id.ToString() + Name).GetMBId(typeof(IndexFolder));
|
|
||||||
|
|
||||||
IndexName = indexName;
|
|
||||||
Parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resets the parent.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parent">The parent.</param>
|
|
||||||
public void ResetParent(Folder parent)
|
|
||||||
{
|
|
||||||
Parent = parent;
|
|
||||||
Id = (parent.Id.ToString() + Name).GetMBId(typeof(IndexFolder));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Override this to true if class should be grouped under a container in indicies
|
|
||||||
/// The container class should be defined via IndexContainer
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public override bool GroupInIndex
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return ShadowItem != null && ShadowItem.GroupInIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override LocationType LocationType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return LocationType.Virtual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Override this to return the folder that should be used to construct a container
|
|
||||||
/// for this item in an index. GroupInIndex should be true as well.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The index container.</value>
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public override Folder IndexContainer
|
|
||||||
{
|
|
||||||
get { return ShadowItem != null ? ShadowItem.IndexContainer : new IndexFolder(this, null, null, "<Unknown>", false); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether [group contents].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [group contents]; otherwise, <c>false</c>.</value>
|
|
||||||
protected bool GroupContents { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the child source.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The child source.</value>
|
|
||||||
protected IEnumerable<BaseItem> ChildSource { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets our children.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>Our children.</value>
|
|
||||||
protected ConcurrentBag<BaseItem> OurChildren { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the index.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The name of the index.</value>
|
|
||||||
public string IndexName { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Override to return the children defined to us when we were created
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The actual children.</value>
|
|
||||||
protected override IEnumerable<BaseItem> LoadChildren()
|
|
||||||
{
|
|
||||||
var originalChildSource = ChildSource.ToList();
|
|
||||||
|
|
||||||
var kids = originalChildSource;
|
|
||||||
if (GroupContents)
|
|
||||||
{
|
|
||||||
// Recursively group up the chain
|
|
||||||
var group = true;
|
|
||||||
var isSubsequentLoop = false;
|
|
||||||
|
|
||||||
while (group)
|
|
||||||
{
|
|
||||||
kids = isSubsequentLoop || kids.Any(i => i.GroupInIndex)
|
|
||||||
? GroupedSource(kids).ToList()
|
|
||||||
: originalChildSource;
|
|
||||||
|
|
||||||
group = kids.Any(i => i.GroupInIndex);
|
|
||||||
isSubsequentLoop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now - since we built the index grouping from the bottom up - we now need to properly set Parents from the top down
|
|
||||||
SetParents(this, kids.OfType<IndexFolder>());
|
|
||||||
|
|
||||||
return kids.DistinctBy(i => i.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the parents.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parent">The parent.</param>
|
|
||||||
/// <param name="kids">The kids.</param>
|
|
||||||
private void SetParents(Folder parent, IEnumerable<IndexFolder> kids)
|
|
||||||
{
|
|
||||||
foreach (var child in kids)
|
|
||||||
{
|
|
||||||
child.ResetParent(parent);
|
|
||||||
child.SetParents(child, child.Children.OfType<IndexFolder>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Groupeds the source.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="source">The source.</param>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
protected IEnumerable<BaseItem> GroupedSource(IEnumerable<BaseItem> source)
|
|
||||||
{
|
|
||||||
return source.GroupBy(i => i.IndexContainer).Select(container => new IndexFolder(this, container.Key, container, null, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The item we are shadowing as a folder (Genre, Actor, etc.)
|
|
||||||
/// We inherit the images and other meta from this item
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The shadow item.</value>
|
|
||||||
protected BaseItem ShadowItem { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the shadow values.
|
|
||||||
/// </summary>
|
|
||||||
protected void SetShadowValues()
|
|
||||||
{
|
|
||||||
if (ShadowItem != null)
|
|
||||||
{
|
|
||||||
Name = ShadowItem.Name;
|
|
||||||
ForcedSortName = ShadowItem.SortName;
|
|
||||||
Genres = ShadowItem.Genres;
|
|
||||||
Studios = ShadowItem.Studios;
|
|
||||||
OfficialRating = ShadowItem.OfficialRatingForComparison;
|
|
||||||
BackdropImagePaths = ShadowItem.BackdropImagePaths;
|
|
||||||
Images = ShadowItem.Images;
|
|
||||||
Overview = ShadowItem.Overview;
|
|
||||||
DisplayMediaType = ShadowItem.GetType().Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Overrides the base implementation to refresh metadata for local trailers
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <param name="forceSave">if set to <c>true</c> [is new item].</param>
|
|
||||||
/// <param name="forceRefresh">if set to <c>true</c> [force].</param>
|
|
||||||
/// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
|
|
||||||
/// <param name="resetResolveArgs">if set to <c>true</c> [reset resolve args].</param>
|
|
||||||
/// <returns>Task{System.Boolean}.</returns>
|
|
||||||
public override Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
|
|
||||||
{
|
|
||||||
// We should never get in here since these are not part of the library
|
|
||||||
return Task.FromResult(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -57,13 +57,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Genre, Rating and Stuido will all be the same
|
// Genre, Rating and Stuido will all be the same
|
||||||
protected override Dictionary<string, Func<User, IEnumerable<BaseItem>>> GetIndexByOptions()
|
protected override IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new Dictionary<string, Func<User, IEnumerable<BaseItem>>> {
|
return new List<string> {
|
||||||
{LocalizedStrings.Instance.GetString("NoneDispPref"), null},
|
{LocalizedStrings.Instance.GetString("NoneDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("PerformerDispPref"), GetIndexByPerformer},
|
{LocalizedStrings.Instance.GetString("PerformerDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("DirectorDispPref"), GetIndexByDirector},
|
{LocalizedStrings.Instance.GetString("DirectorDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("YearDispPref"), GetIndexByYear},
|
{LocalizedStrings.Instance.GetString("YearDispPref")},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
.Cast<Episode>();
|
.Cast<Episode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null)
|
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
{
|
{
|
||||||
return GetEpisodes(user);
|
return GetEpisodes(user);
|
||||||
}
|
}
|
||||||
|
@ -89,13 +89,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Studio, Genre and Rating will all be the same so makes no sense to index by these
|
// Studio, Genre and Rating will all be the same so makes no sense to index by these
|
||||||
protected override Dictionary<string, Func<User, IEnumerable<BaseItem>>> GetIndexByOptions()
|
protected override IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new Dictionary<string, Func<User, IEnumerable<BaseItem>>> {
|
return new List<string> {
|
||||||
{LocalizedStrings.Instance.GetString("NoneDispPref"), null},
|
{LocalizedStrings.Instance.GetString("NoneDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("PerformerDispPref"), GetIndexByPerformer},
|
{LocalizedStrings.Instance.GetString("PerformerDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("DirectorDispPref"), GetIndexByDirector},
|
{LocalizedStrings.Instance.GetString("DirectorDispPref")},
|
||||||
{LocalizedStrings.Instance.GetString("YearDispPref"), GetIndexByYear},
|
{LocalizedStrings.Instance.GetString("YearDispPref")},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null)
|
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
{
|
{
|
||||||
return GetSeasons(user);
|
return GetSeasons(user);
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,6 @@
|
|||||||
<Compile Include="Entities\Folder.cs" />
|
<Compile Include="Entities\Folder.cs" />
|
||||||
<Compile Include="Entities\Genre.cs" />
|
<Compile Include="Entities\Genre.cs" />
|
||||||
<Compile Include="Entities\ICollectionFolder.cs" />
|
<Compile Include="Entities\ICollectionFolder.cs" />
|
||||||
<Compile Include="Entities\IndexFolder.cs" />
|
|
||||||
<Compile Include="Entities\IVirtualFolderCreator.cs" />
|
<Compile Include="Entities\IVirtualFolderCreator.cs" />
|
||||||
<Compile Include="Entities\Movies\BoxSet.cs" />
|
<Compile Include="Entities\Movies\BoxSet.cs" />
|
||||||
<Compile Include="Entities\Movies\Movie.cs" />
|
<Compile Include="Entities\Movies\Movie.cs" />
|
||||||
|
@ -140,12 +140,6 @@ namespace MediaBrowser.Model.Querying
|
|||||||
/// <value>The index by.</value>
|
/// <value>The index by.</value>
|
||||||
public string SearchTerm { get; set; }
|
public string SearchTerm { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The dynamic, localized index function name
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The index by.</value>
|
|
||||||
public string IndexBy { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image types.
|
/// Gets or sets the image types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -292,8 +292,6 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string IndexFolderDelimeter = "-index-";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets client-side Id of a server-side BaseItem
|
/// Gets client-side Id of a server-side BaseItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -307,13 +305,6 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
throw new ArgumentNullException("item");
|
throw new ArgumentNullException("item");
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexFolder = item as IndexFolder;
|
|
||||||
|
|
||||||
if (indexFolder != null)
|
|
||||||
{
|
|
||||||
return GetDtoId(indexFolder.Parent) + IndexFolderDelimeter + (indexFolder.IndexName ?? string.Empty) + IndexFolderDelimeter + indexFolder.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.Id.ToString("N");
|
return item.Id.ToString("N");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,26 +609,15 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
throw new ArgumentNullException("id");
|
throw new ArgumentNullException("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the item is an indexed folder we have to do a special routine to get it
|
|
||||||
var isIndexFolder = id.IndexOf(IndexFolderDelimeter, StringComparison.OrdinalIgnoreCase) != -1;
|
|
||||||
|
|
||||||
if (isIndexFolder)
|
|
||||||
{
|
|
||||||
if (userId.HasValue)
|
|
||||||
{
|
|
||||||
return GetIndexFolder(id, userId.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseItem item = null;
|
BaseItem item = null;
|
||||||
|
|
||||||
if (userId.HasValue || !isIndexFolder)
|
if (userId.HasValue)
|
||||||
{
|
{
|
||||||
item = _libraryManager.GetItemById(new Guid(id));
|
item = _libraryManager.GetItemById(new Guid(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we still don't find it, look within individual user views
|
// If we still don't find it, look within individual user views
|
||||||
if (item == null && !userId.HasValue && isIndexFolder)
|
if (item == null && !userId.HasValue)
|
||||||
{
|
{
|
||||||
foreach (var user in _userManager.Users)
|
foreach (var user in _userManager.Users)
|
||||||
{
|
{
|
||||||
@ -653,60 +633,6 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds an index folder based on an Id and userId
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The id.</param>
|
|
||||||
/// <param name="userId">The user id.</param>
|
|
||||||
/// <returns>BaseItem.</returns>
|
|
||||||
private BaseItem GetIndexFolder(string id, Guid userId)
|
|
||||||
{
|
|
||||||
var user = _userManager.GetUserById(userId);
|
|
||||||
|
|
||||||
var stringSeparators = new[] { IndexFolderDelimeter };
|
|
||||||
|
|
||||||
// Split using the delimeter
|
|
||||||
var values = id.Split(stringSeparators, StringSplitOptions.None).ToList();
|
|
||||||
|
|
||||||
// Get the top folder normally using the first id
|
|
||||||
var folder = GetItemByDtoId(values[0], userId) as Folder;
|
|
||||||
|
|
||||||
values.RemoveAt(0);
|
|
||||||
|
|
||||||
// Get indexed folders using the remaining values in the id string
|
|
||||||
return GetIndexFolder(values, folder, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets indexed folders based on a list of index names and folder id's
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">The values.</param>
|
|
||||||
/// <param name="parentFolder">The parent folder.</param>
|
|
||||||
/// <param name="user">The user.</param>
|
|
||||||
/// <returns>BaseItem.</returns>
|
|
||||||
private BaseItem GetIndexFolder(List<string> values, Folder parentFolder, User user)
|
|
||||||
{
|
|
||||||
// The index name is first
|
|
||||||
var indexBy = values[0];
|
|
||||||
|
|
||||||
// The index folder id is next
|
|
||||||
var indexFolderId = new Guid(values[1]);
|
|
||||||
|
|
||||||
// Remove them from the lst
|
|
||||||
values.RemoveRange(0, 2);
|
|
||||||
|
|
||||||
// Get the IndexFolder
|
|
||||||
var indexFolder = parentFolder.GetChildren(user, false, indexBy).FirstOrDefault(i => i.Id == indexFolderId) as Folder;
|
|
||||||
|
|
||||||
// Nested index folder
|
|
||||||
if (values.Count > 0)
|
|
||||||
{
|
|
||||||
return GetIndexFolder(values, indexFolder, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets simple property values on a DTOBaseItem
|
/// Sets simple property values on a DTOBaseItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -100,7 +100,7 @@ namespace MediaBrowser.ServerApplication
|
|||||||
var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.DisplayPreferencesId, (ddlProfile.SelectedItem as User).Id, "LibraryExplorer") ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
|
var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.DisplayPreferencesId, (ddlProfile.SelectedItem as User).Id, "LibraryExplorer") ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
|
||||||
var node = new TreeViewItem { Tag = currentFolder };
|
var node = new TreeViewItem { Tag = currentFolder };
|
||||||
|
|
||||||
var subChildren = currentFolder.GetChildren(CurrentUser, true, prefs.IndexBy);
|
var subChildren = currentFolder.GetChildren(CurrentUser, true);
|
||||||
subChildren = OrderByName(subChildren, CurrentUser);
|
subChildren = OrderByName(subChildren, CurrentUser);
|
||||||
AddChildren(node, subChildren, CurrentUser);
|
AddChildren(node, subChildren, CurrentUser);
|
||||||
node.Header = currentFolder.Name + " (" +
|
node.Header = currentFolder.Name + " (" +
|
||||||
@ -371,7 +371,7 @@ namespace MediaBrowser.ServerApplication
|
|||||||
//re-build the current item's children as an index
|
//re-build the current item's children as an index
|
||||||
prefs.IndexBy = ddlIndexBy.SelectedItem as string;
|
prefs.IndexBy = ddlIndexBy.SelectedItem as string;
|
||||||
treeItem.Items.Clear();
|
treeItem.Items.Clear();
|
||||||
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser);
|
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true), CurrentUser, prefs.SortBy), CurrentUser);
|
||||||
treeItem.Header = folder.Name + "(" +
|
treeItem.Header = folder.Name + "(" +
|
||||||
treeItem.Items.Count + ")";
|
treeItem.Items.Count + ")";
|
||||||
Cursor = Cursors.Arrow;
|
Cursor = Cursors.Arrow;
|
||||||
@ -412,7 +412,7 @@ namespace MediaBrowser.ServerApplication
|
|||||||
//re-sort
|
//re-sort
|
||||||
prefs.SortBy = ddlSortBy.SelectedItem as string;
|
prefs.SortBy = ddlSortBy.SelectedItem as string;
|
||||||
treeItem.Items.Clear();
|
treeItem.Items.Clear();
|
||||||
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser);
|
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser);
|
||||||
treeItem.Header = folder.Name + "(" +
|
treeItem.Header = folder.Name + "(" +
|
||||||
treeItem.Items.Count + ")";
|
treeItem.Items.Count + ")";
|
||||||
Cursor = Cursors.Arrow;
|
Cursor = Cursors.Arrow;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user