mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-04 03:27:21 -05:00 
			
		
		
		
	#715 - Support creating/editing collections (boxsets) in web client
This commit is contained in:
		
							parent
							
								
									c85f2957d9
								
							
						
					
					
						commit
						e00985d07c
					
				@ -66,6 +66,7 @@
 | 
				
			|||||||
    <Compile Include="..\SharedVersion.cs">
 | 
					    <Compile Include="..\SharedVersion.cs">
 | 
				
			||||||
      <Link>Properties\SharedVersion.cs</Link>
 | 
					      <Link>Properties\SharedVersion.cs</Link>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="Movies\CollectionService.cs" />
 | 
				
			||||||
    <Compile Include="Music\AlbumsService.cs" />
 | 
					    <Compile Include="Music\AlbumsService.cs" />
 | 
				
			||||||
    <Compile Include="AppThemeService.cs" />
 | 
					    <Compile Include="AppThemeService.cs" />
 | 
				
			||||||
    <Compile Include="BaseApiService.cs" />
 | 
					    <Compile Include="BaseApiService.cs" />
 | 
				
			||||||
@ -91,7 +92,7 @@
 | 
				
			|||||||
    <Compile Include="Library\LibraryStructureService.cs" />
 | 
					    <Compile Include="Library\LibraryStructureService.cs" />
 | 
				
			||||||
    <Compile Include="LiveTv\LiveTvService.cs" />
 | 
					    <Compile Include="LiveTv\LiveTvService.cs" />
 | 
				
			||||||
    <Compile Include="LocalizationService.cs" />
 | 
					    <Compile Include="LocalizationService.cs" />
 | 
				
			||||||
    <Compile Include="MoviesService.cs" />
 | 
					    <Compile Include="Movies\MoviesService.cs" />
 | 
				
			||||||
    <Compile Include="NewsService.cs" />
 | 
					    <Compile Include="NewsService.cs" />
 | 
				
			||||||
    <Compile Include="NotificationsService.cs" />
 | 
					    <Compile Include="NotificationsService.cs" />
 | 
				
			||||||
    <Compile Include="PackageReviewService.cs" />
 | 
					    <Compile Include="PackageReviewService.cs" />
 | 
				
			||||||
@ -118,7 +119,7 @@
 | 
				
			|||||||
    <Compile Include="SessionsService.cs" />
 | 
					    <Compile Include="SessionsService.cs" />
 | 
				
			||||||
    <Compile Include="SimilarItemsHelper.cs" />
 | 
					    <Compile Include="SimilarItemsHelper.cs" />
 | 
				
			||||||
    <Compile Include="SystemService.cs" />
 | 
					    <Compile Include="SystemService.cs" />
 | 
				
			||||||
    <Compile Include="TrailersService.cs" />
 | 
					    <Compile Include="Movies\TrailersService.cs" />
 | 
				
			||||||
    <Compile Include="TvShowsService.cs" />
 | 
					    <Compile Include="TvShowsService.cs" />
 | 
				
			||||||
    <Compile Include="UserLibrary\ArtistsService.cs" />
 | 
					    <Compile Include="UserLibrary\ArtistsService.cs" />
 | 
				
			||||||
    <Compile Include="UserLibrary\BaseItemsByNameService.cs" />
 | 
					    <Compile Include="UserLibrary\BaseItemsByNameService.cs" />
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										80
									
								
								MediaBrowser.Api/Movies/CollectionService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								MediaBrowser.Api/Movies/CollectionService.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Controller.Collections;
 | 
				
			||||||
 | 
					using ServiceStack;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Api.Movies
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [Route("/Collections", "POST")]
 | 
				
			||||||
 | 
					    [Api(Description = "Creates a new collection")]
 | 
				
			||||||
 | 
					    public class CreateCollection : IReturnVoid
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [ApiMember(Name = "IsLocked", Description = "Whether or not to lock the new collection.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
 | 
				
			||||||
 | 
					        public bool IsLocked { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ApiMember(Name = "Name", Description = "The name of the new collection.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
 | 
				
			||||||
 | 
					        public string Name { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ApiMember(Name = "ParentId", Description = "Optional - create the collection within a specific folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
 | 
				
			||||||
 | 
					        public Guid? ParentId { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Route("/Collections/{Id}/Items", "POST")]
 | 
				
			||||||
 | 
					    [Api(Description = "Adds items to a collection")]
 | 
				
			||||||
 | 
					    public class AddToCollection : IReturnVoid
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
 | 
				
			||||||
 | 
					        public string Ids { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
 | 
				
			||||||
 | 
					        public Guid Id { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Route("/Collections/{Id}/Items", "DELETE")]
 | 
				
			||||||
 | 
					    [Api(Description = "Removes items from a collection")]
 | 
				
			||||||
 | 
					    public class RemoveFromCollection : IReturnVoid
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
 | 
				
			||||||
 | 
					        public string Ids { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
 | 
				
			||||||
 | 
					        public Guid Id { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class CollectionService : BaseApiService
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly ICollectionManager _collectionManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public CollectionService(ICollectionManager collectionManager)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _collectionManager = collectionManager;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Post(CreateCollection request)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var task = _collectionManager.CreateCollection(new CollectionCreationOptions
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                IsLocked = request.IsLocked,
 | 
				
			||||||
 | 
					                Name = request.Name,
 | 
				
			||||||
 | 
					                ParentId = request.ParentId
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Task.WaitAll(task);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Post(AddToCollection request)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var task = _collectionManager.AddToCollection(request.Id, request.Ids.Split(',').Select(i => new Guid(i)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Task.WaitAll(task);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Delete(RemoveFromCollection request)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var task = _collectionManager.RemoveFromCollection(request.Id, request.Ids.Split(',').Select(i => new Guid(i)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Task.WaitAll(task);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,7 +5,7 @@ using MediaBrowser.Controller.Library;
 | 
				
			|||||||
using MediaBrowser.Controller.Persistence;
 | 
					using MediaBrowser.Controller.Persistence;
 | 
				
			||||||
using ServiceStack;
 | 
					using ServiceStack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MediaBrowser.Api
 | 
					namespace MediaBrowser.Api.Movies
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Class GetSimilarMovies
 | 
					    /// Class GetSimilarMovies
 | 
				
			||||||
@ -5,7 +5,7 @@ using MediaBrowser.Controller.Library;
 | 
				
			|||||||
using MediaBrowser.Controller.Persistence;
 | 
					using MediaBrowser.Controller.Persistence;
 | 
				
			||||||
using ServiceStack;
 | 
					using ServiceStack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MediaBrowser.Api
 | 
					namespace MediaBrowser.Api.Movies
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Class GetSimilarTrailers
 | 
					    /// Class GetSimilarTrailers
 | 
				
			||||||
@ -63,6 +63,9 @@ namespace MediaBrowser.Api
 | 
				
			|||||||
        [ApiMember(Name = "IncludeArtists", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
 | 
					        [ApiMember(Name = "IncludeArtists", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
 | 
				
			||||||
        public bool IncludeArtists { get; set; }
 | 
					        public bool IncludeArtists { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
 | 
				
			||||||
 | 
					        public string IncludeItemTypes { get; set; }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        public GetSearchHints()
 | 
					        public GetSearchHints()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            IncludeArtists = true;
 | 
					            IncludeArtists = true;
 | 
				
			||||||
@ -130,7 +133,8 @@ namespace MediaBrowser.Api
 | 
				
			|||||||
                IncludePeople = request.IncludePeople,
 | 
					                IncludePeople = request.IncludePeople,
 | 
				
			||||||
                IncludeStudios = request.IncludeStudios,
 | 
					                IncludeStudios = request.IncludeStudios,
 | 
				
			||||||
                StartIndex = request.StartIndex,
 | 
					                StartIndex = request.StartIndex,
 | 
				
			||||||
                UserId = request.UserId
 | 
					                UserId = request.UserId,
 | 
				
			||||||
 | 
					                IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }).ConfigureAwait(false);
 | 
					            }).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ namespace MediaBrowser.Controller.Collections
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        public string Name { get; set; }
 | 
					        public string Name { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Guid ParentId { get; set; }
 | 
					        public Guid? ParentId { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsLocked { get; set; }
 | 
					        public bool IsLocked { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace MediaBrowser.Controller.Collections
 | 
					namespace MediaBrowser.Controller.Collections
 | 
				
			||||||
@ -16,16 +17,16 @@ namespace MediaBrowser.Controller.Collections
 | 
				
			|||||||
        /// Adds to collection.
 | 
					        /// Adds to collection.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="collectionId">The collection identifier.</param>
 | 
					        /// <param name="collectionId">The collection identifier.</param>
 | 
				
			||||||
        /// <param name="itemId">The item identifier.</param>
 | 
					        /// <param name="itemIds">The item ids.</param>
 | 
				
			||||||
        /// <returns>Task.</returns>
 | 
					        /// <returns>Task.</returns>
 | 
				
			||||||
        Task AddToCollection(Guid collectionId, Guid itemId);
 | 
					        Task AddToCollection(Guid collectionId, IEnumerable<Guid> itemIds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Removes from collection.
 | 
					        /// Removes from collection.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="collectionId">The collection identifier.</param>
 | 
					        /// <param name="collectionId">The collection identifier.</param>
 | 
				
			||||||
        /// <param name="itemId">The item identifier.</param>
 | 
					        /// <param name="itemIds">The item ids.</param>
 | 
				
			||||||
        /// <returns>Task.</returns>
 | 
					        /// <returns>Task.</returns>
 | 
				
			||||||
        Task RemoveFromCollection(Guid collectionId, Guid itemId);
 | 
					        Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -124,6 +124,15 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [IgnoreDataMember]
 | 
				
			||||||
 | 
					        public virtual bool IsHidden
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [IgnoreDataMember]
 | 
					        [IgnoreDataMember]
 | 
				
			||||||
        public virtual bool IsOwnedItem
 | 
					        public virtual bool IsOwnedItem
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
using MediaBrowser.Model.Entities;
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace MediaBrowser.Controller.Entities
 | 
					namespace MediaBrowser.Controller.Entities
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
@ -8,18 +7,6 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public abstract class BasePluginFolder : Folder, ICollectionFolder, IByReferenceItem
 | 
					    public abstract class BasePluginFolder : Folder, ICollectionFolder, IByReferenceItem
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Gets or sets the type of the location.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <value>The type of the location.</value>
 | 
					 | 
				
			||||||
        public override LocationType LocationType
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return LocationType.Virtual;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        protected BasePluginFolder()
 | 
					        protected BasePluginFolder()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            DisplayMediaType = "CollectionFolder";
 | 
					            DisplayMediaType = "CollectionFolder";
 | 
				
			||||||
 | 
				
			|||||||
@ -264,7 +264,7 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
        [IgnoreDataMember]
 | 
					        [IgnoreDataMember]
 | 
				
			||||||
        public IEnumerable<BaseItem> Children
 | 
					        public IEnumerable<BaseItem> Children
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return ActualChildren; }
 | 
					            get { return ActualChildren.Where(i => !i.IsHidden); }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -905,13 +905,6 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
        /// <returns>BaseItem.</returns>
 | 
					        /// <returns>BaseItem.</returns>
 | 
				
			||||||
        private BaseItem GetLinkedChild(LinkedChild info)
 | 
					        private BaseItem GetLinkedChild(LinkedChild info)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (string.IsNullOrEmpty(info.Path))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                throw new ArgumentException("Encountered linked child with empty path.");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            BaseItem item = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // First get using the cached Id
 | 
					            // First get using the cached Id
 | 
				
			||||||
            if (info.ItemId.HasValue)
 | 
					            if (info.ItemId.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -920,20 +913,19 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
                    return null;
 | 
					                    return null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                item = LibraryManager.GetItemById(info.ItemId.Value);
 | 
					                var itemById = LibraryManager.GetItemById(info.ItemId.Value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (itemById != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return itemById;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If still null, search by path
 | 
					            var item = FindLinkedChild(info);
 | 
				
			||||||
            if (item == null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                item = LibraryManager.RootFolder.FindByPath(info.Path);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If still null, log
 | 
					            // If still null, log
 | 
				
			||||||
            if (item == null)
 | 
					            if (item == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Logger.Warn("Unable to find linked item at {0}", info.Path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Don't keep searching over and over
 | 
					                // Don't keep searching over and over
 | 
				
			||||||
                info.ItemId = Guid.Empty;
 | 
					                info.ItemId = Guid.Empty;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -946,6 +938,43 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return item;
 | 
					            return item;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private BaseItem FindLinkedChild(LinkedChild info)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!string.IsNullOrEmpty(info.Path))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var itemByPath = LibraryManager.RootFolder.FindByPath(info.Path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (itemByPath == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Logger.Warn("Unable to find linked item at path {0}", info.Path);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return itemByPath;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!string.IsNullOrWhiteSpace(info.ItemName) && !string.IsNullOrWhiteSpace(info.ItemType))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return LibraryManager.RootFolder.RecursiveChildren.FirstOrDefault(i =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (string.Equals(i.Name, info.ItemName, StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (string.Equals(i.GetType().Name, info.ItemType, StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            if (info.ItemYear.HasValue)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                return info.ItemYear.Value == (i.ProductionYear ?? -1);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            return true;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
 | 
					        protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var changesFound = false;
 | 
					            var changesFound = false;
 | 
				
			||||||
@ -1106,5 +1135,10 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
            return GetRecursiveChildren(user).Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual)
 | 
					            return GetRecursiveChildren(user).Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual)
 | 
				
			||||||
                .All(i => i.IsUnplayed(user));
 | 
					                .All(i => i.IsUnplayed(user));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerable<BaseItem> GetHiddenChildren()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ActualChildren.Where(i => i.IsHidden);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,10 @@ namespace MediaBrowser.Controller.Entities
 | 
				
			|||||||
        public string Path { get; set; }
 | 
					        public string Path { get; set; }
 | 
				
			||||||
        public LinkedChildType Type { get; set; }
 | 
					        public LinkedChildType Type { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string ItemName { get; set; }
 | 
				
			||||||
 | 
					        public string ItemType { get; set; }
 | 
				
			||||||
 | 
					        public int? ItemYear { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Serves as a cache
 | 
					        /// Serves as a cache
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,8 @@ namespace MediaBrowser.Model.Search
 | 
				
			|||||||
        public bool IncludeStudios { get; set; }
 | 
					        public bool IncludeStudios { get; set; }
 | 
				
			||||||
        public bool IncludeArtists { get; set; }
 | 
					        public bool IncludeArtists { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string[] IncludeItemTypes { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public SearchQuery()
 | 
					        public SearchQuery()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            IncludeArtists = true;
 | 
					            IncludeArtists = true;
 | 
				
			||||||
@ -40,6 +42,8 @@ namespace MediaBrowser.Model.Search
 | 
				
			|||||||
            IncludeMedia = true;
 | 
					            IncludeMedia = true;
 | 
				
			||||||
            IncludePeople = true;
 | 
					            IncludePeople = true;
 | 
				
			||||||
            IncludeStudios = true;
 | 
					            IncludeStudios = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IncludeItemTypes = new string[] { };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
 | 
					using MediaBrowser.Controller.Entities.Movies;
 | 
				
			||||||
using MediaBrowser.Controller.Entities.TV;
 | 
					using MediaBrowser.Controller.Entities.TV;
 | 
				
			||||||
using MediaBrowser.Controller.Persistence;
 | 
					using MediaBrowser.Controller.Persistence;
 | 
				
			||||||
using MediaBrowser.Model.Entities;
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
@ -82,7 +83,8 @@ namespace MediaBrowser.Providers.Savers
 | 
				
			|||||||
                    "TVRageId",
 | 
					                    "TVRageId",
 | 
				
			||||||
                    "VoteCount",
 | 
					                    "VoteCount",
 | 
				
			||||||
                    "Website",
 | 
					                    "Website",
 | 
				
			||||||
                    "Zap2ItId"
 | 
					                    "Zap2ItId",
 | 
				
			||||||
 | 
					                    "CollectionItems"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
 | 
					        }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -580,6 +582,12 @@ namespace MediaBrowser.Providers.Savers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                builder.Append("</Persons>");
 | 
					                builder.Append("</Persons>");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var folder = item as BoxSet;
 | 
				
			||||||
 | 
					            if (folder != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                AddCollectionItems(folder, builder);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository)
 | 
					        public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository)
 | 
				
			||||||
@ -631,5 +639,34 @@ namespace MediaBrowser.Providers.Savers
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static void AddCollectionItems(Folder item, StringBuilder builder)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var items = item.LinkedChildren
 | 
				
			||||||
 | 
					                .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName))
 | 
				
			||||||
 | 
					                .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (items.Count == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            builder.Append("<CollectionItems>");
 | 
				
			||||||
 | 
					            foreach (var link in items)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                builder.Append("<CollectionItem>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                builder.Append("<Name>" + SecurityElement.Escape(link.ItemName) + "</Name>");
 | 
				
			||||||
 | 
					                builder.Append("<Type>" + SecurityElement.Escape(link.ItemType) + "</Type>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (link.ItemYear.HasValue)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    builder.Append("<Year>" + SecurityElement.Escape(link.ItemYear.Value.ToString(UsCulture)) + "</Year>");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                builder.Append("</CollectionItem>");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            builder.Append("</CollectionItems>");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,9 @@ using MediaBrowser.Controller.Entities.Movies;
 | 
				
			|||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Providers;
 | 
					using MediaBrowser.Controller.Providers;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.Collections
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var folderName = _fileSystem.GetValidFilename(name);
 | 
					            var folderName = _fileSystem.GetValidFilename(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var parentFolder = _libraryManager.GetItemById(options.ParentId) as Folder;
 | 
					            var parentFolder = GetParentFolder(options.ParentId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (parentFolder == null)
 | 
					            if (parentFolder == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -66,14 +68,94 @@ namespace MediaBrowser.Server.Implementations.Collections
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Task AddToCollection(Guid collectionId, Guid itemId)
 | 
					        private Folder GetParentFolder(Guid? parentId)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            throw new NotImplementedException();
 | 
					            if (parentId.HasValue)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (parentId.Value == Guid.Empty)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new ArgumentNullException("parentId");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Task RemoveFromCollection(Guid collectionId, Guid itemId)
 | 
					                return _libraryManager.GetItemById(parentId.Value) as Folder;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>().FirstOrDefault() ??
 | 
				
			||||||
 | 
					                _libraryManager.RootFolder.GetHiddenChildren().OfType<ManualCollectionsFolder>().FirstOrDefault();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            throw new NotImplementedException();
 | 
					            var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (collection == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new ArgumentException("No collection exists with the supplied Id");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var list = new List<LinkedChild>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var itemId in ids)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var item = _libraryManager.GetItemById(itemId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (item == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new ArgumentException("No item exists with the supplied Id");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (collection.LinkedChildren.Any(i => i.ItemId.HasValue && i.ItemId == itemId))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new ArgumentException("Item already exists in collection");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                list.Add(new LinkedChild
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ItemName = item.Name,
 | 
				
			||||||
 | 
					                    ItemYear = item.ProductionYear,
 | 
				
			||||||
 | 
					                    ItemType = item.GetType().Name,
 | 
				
			||||||
 | 
					                    Type = LinkedChildType.Manual
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            collection.LinkedChildren.AddRange(list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (collection == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new ArgumentException("No collection exists with the supplied Id");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var list = new List<LinkedChild>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var itemId in itemIds)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var child = collection.LinkedChildren.FirstOrDefault(i => i.ItemId.HasValue && i.ItemId.Value == itemId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (child == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    throw new ArgumentException("No collection title exists with the supplied Id");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                list.Add(child);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var child in list)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                collection.LinkedChildren.Remove(child);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					using MediaBrowser.Common.Configuration;
 | 
				
			||||||
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MediaBrowser.Server.Implementations.Collections
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class CollectionsDynamicFolder : IVirtualFolderCreator
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly IApplicationPaths _appPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public CollectionsDynamicFolder(IApplicationPaths appPaths)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _appPaths = appPaths;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public BasePluginFolder GetFolder()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var path = Path.Combine(_appPaths.DataPath, "collections");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Directory.CreateDirectory(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new ManualCollectionsFolder
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Path = path
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class ManualCollectionsFolder : BasePluginFolder
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public ManualCollectionsFolder()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Name = "Collections";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override bool IsVisible(User user)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!GetChildren(user, true).Any())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return base.IsVisible(user);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override bool IsHidden
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return !ActualChildren.Any() || base.IsHidden;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -37,6 +37,12 @@ namespace MediaBrowser.Server.Implementations.Library
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var results = await GetSearchHints(inputItems, query).ConfigureAwait(false);
 | 
					            var results = await GetSearchHints(inputItems, query).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Include item types
 | 
				
			||||||
 | 
					            if (query.IncludeItemTypes.Length > 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                results = results.Where(f => query.IncludeItemTypes.Contains(f.Item.GetType().Name, StringComparer.OrdinalIgnoreCase));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var searchResultArray = results.ToArray();
 | 
					            var searchResultArray = results.ToArray();
 | 
				
			||||||
            results = searchResultArray;
 | 
					            results = searchResultArray;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -583,6 +583,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 | 
				
			|||||||
                .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
 | 
					                .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            programs = programList.OrderByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
 | 
					            programs = programList.OrderByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
 | 
				
			||||||
 | 
					                .ThenBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
 | 
				
			||||||
                .ThenBy(i => i.StartDate);
 | 
					                .ThenBy(i => i.StartDate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (query.Limit.HasValue)
 | 
					            if (query.Limit.HasValue)
 | 
				
			||||||
 | 
				
			|||||||
@ -65,12 +65,9 @@
 | 
				
			|||||||
    </Reference>
 | 
					    </Reference>
 | 
				
			||||||
    <Reference Include="System" />
 | 
					    <Reference Include="System" />
 | 
				
			||||||
    <Reference Include="System.Core" />
 | 
					    <Reference Include="System.Core" />
 | 
				
			||||||
    <Reference Include="System.Data.SQLite, Version=1.0.90.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
 | 
					    <Reference Include="System.Data.SQLite, Version=1.0.91.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
 | 
				
			||||||
      <SpecificVersion>False</SpecificVersion>
 | 
					      <SpecificVersion>False</SpecificVersion>
 | 
				
			||||||
      <HintPath>..\packages\System.Data.SQLite.x86.1.0.90.0\lib\net45\System.Data.SQLite.dll</HintPath>
 | 
					      <HintPath>..\packages\System.Data.SQLite.Core.1.0.91.3\lib\net45\System.Data.SQLite.dll</HintPath>
 | 
				
			||||||
    </Reference>
 | 
					 | 
				
			||||||
    <Reference Include="System.Data.SQLite.Linq" Condition=" '$(ConfigurationName)' != 'Release Mono' ">
 | 
					 | 
				
			||||||
      <HintPath>..\packages\System.Data.SQLite.x86.1.0.90.0\lib\net45\System.Data.SQLite.Linq.dll</HintPath>
 | 
					 | 
				
			||||||
    </Reference>
 | 
					    </Reference>
 | 
				
			||||||
    <Reference Include="System.Drawing" />
 | 
					    <Reference Include="System.Drawing" />
 | 
				
			||||||
    <Reference Include="Microsoft.CSharp" />
 | 
					    <Reference Include="Microsoft.CSharp" />
 | 
				
			||||||
@ -110,6 +107,7 @@
 | 
				
			|||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="BdInfo\BdInfoExaminer.cs" />
 | 
					    <Compile Include="BdInfo\BdInfoExaminer.cs" />
 | 
				
			||||||
    <Compile Include="Collections\CollectionManager.cs" />
 | 
					    <Compile Include="Collections\CollectionManager.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Collections\CollectionsDynamicFolder.cs" />
 | 
				
			||||||
    <Compile Include="Configuration\ServerConfigurationManager.cs" />
 | 
					    <Compile Include="Configuration\ServerConfigurationManager.cs" />
 | 
				
			||||||
    <Compile Include="Drawing\ImageHeader.cs" />
 | 
					    <Compile Include="Drawing\ImageHeader.cs" />
 | 
				
			||||||
    <Compile Include="Drawing\PercentPlayedDrawer.cs" />
 | 
					    <Compile Include="Drawing\PercentPlayedDrawer.cs" />
 | 
				
			||||||
@ -378,6 +376,12 @@
 | 
				
			|||||||
      <Link>swagger-ui\swagger-ui.min.js</Link>
 | 
					      <Link>swagger-ui\swagger-ui.min.js</Link>
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
 | 
					    <Content Include="x64\SQLite.Interop.dll">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </Content>
 | 
				
			||||||
 | 
					    <Content Include="x86\SQLite.Interop.dll">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </Content>
 | 
				
			||||||
    <EmbeddedResource Include="Localization\Ratings\be.txt" />
 | 
					    <EmbeddedResource Include="Localization\Ratings\be.txt" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
				
			|||||||
@ -4,5 +4,5 @@
 | 
				
			|||||||
  <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
 | 
					  <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
 | 
				
			||||||
  <package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
 | 
					  <package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
 | 
				
			||||||
  <package id="morelinq" version="1.0.16006" targetFramework="net45" />
 | 
					  <package id="morelinq" version="1.0.16006" targetFramework="net45" />
 | 
				
			||||||
  <package id="System.Data.SQLite.x86" version="1.0.90.0" targetFramework="net45" />
 | 
					  <package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" />
 | 
				
			||||||
</packages>
 | 
					</packages>
 | 
				
			||||||
@ -2,6 +2,8 @@
 | 
				
			|||||||
<configuration>
 | 
					<configuration>
 | 
				
			||||||
  <configSections>
 | 
					  <configSections>
 | 
				
			||||||
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
 | 
					    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
 | 
				
			||||||
  </configSections>
 | 
					  </configSections>
 | 
				
			||||||
  <system.diagnostics>
 | 
					  <system.diagnostics>
 | 
				
			||||||
    <assert assertuienabled="false" />
 | 
					    <assert assertuienabled="false" />
 | 
				
			||||||
@ -43,7 +45,7 @@
 | 
				
			|||||||
      </dependentAssembly>
 | 
					      </dependentAssembly>
 | 
				
			||||||
      <dependentAssembly>
 | 
					      <dependentAssembly>
 | 
				
			||||||
        <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
 | 
					        <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
 | 
				
			||||||
        <bindingRedirect oldVersion="0.0.0.0-1.0.89.0" newVersion="1.0.89.0" />
 | 
					        <bindingRedirect oldVersion="0.0.0.0-1.0.91.0" newVersion="1.0.91.0" />
 | 
				
			||||||
      </dependentAssembly>
 | 
					      </dependentAssembly>
 | 
				
			||||||
      <dependentAssembly>
 | 
					      <dependentAssembly>
 | 
				
			||||||
        <assemblyIdentity name="SimpleInjector" publicKeyToken="984cb50dea722e99" culture="neutral" />
 | 
					        <assemblyIdentity name="SimpleInjector" publicKeyToken="984cb50dea722e99" culture="neutral" />
 | 
				
			||||||
@ -63,4 +65,16 @@
 | 
				
			|||||||
      </providers>
 | 
					      </providers>
 | 
				
			||||||
    </roleManager>
 | 
					    </roleManager>
 | 
				
			||||||
  </system.web>
 | 
					  </system.web>
 | 
				
			||||||
 | 
					  <entityFramework>
 | 
				
			||||||
 | 
					    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
 | 
				
			||||||
 | 
					      <parameters>
 | 
				
			||||||
 | 
					        <parameter value="v11.0" />
 | 
				
			||||||
 | 
					      </parameters>
 | 
				
			||||||
 | 
					    </defaultConnectionFactory>
 | 
				
			||||||
 | 
					    <providers>
 | 
				
			||||||
 | 
					      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
 | 
				
			||||||
 | 
					      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
 | 
				
			||||||
 | 
					    </providers>
 | 
				
			||||||
 | 
					  </entityFramework>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
</configuration>
 | 
					</configuration>
 | 
				
			||||||
@ -9,6 +9,7 @@ using MediaBrowser.Common.IO;
 | 
				
			|||||||
using MediaBrowser.Common.Net;
 | 
					using MediaBrowser.Common.Net;
 | 
				
			||||||
using MediaBrowser.Common.Progress;
 | 
					using MediaBrowser.Common.Progress;
 | 
				
			||||||
using MediaBrowser.Controller;
 | 
					using MediaBrowser.Controller;
 | 
				
			||||||
 | 
					using MediaBrowser.Controller.Collections;
 | 
				
			||||||
using MediaBrowser.Controller.Configuration;
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
using MediaBrowser.Controller.Drawing;
 | 
					using MediaBrowser.Controller.Drawing;
 | 
				
			||||||
using MediaBrowser.Controller.Dto;
 | 
					using MediaBrowser.Controller.Dto;
 | 
				
			||||||
@ -36,6 +37,7 @@ using MediaBrowser.Model.Updates;
 | 
				
			|||||||
using MediaBrowser.Providers.Manager;
 | 
					using MediaBrowser.Providers.Manager;
 | 
				
			||||||
using MediaBrowser.Server.Implementations;
 | 
					using MediaBrowser.Server.Implementations;
 | 
				
			||||||
using MediaBrowser.Server.Implementations.BdInfo;
 | 
					using MediaBrowser.Server.Implementations.BdInfo;
 | 
				
			||||||
 | 
					using MediaBrowser.Server.Implementations.Collections;
 | 
				
			||||||
using MediaBrowser.Server.Implementations.Configuration;
 | 
					using MediaBrowser.Server.Implementations.Configuration;
 | 
				
			||||||
using MediaBrowser.Server.Implementations.Drawing;
 | 
					using MediaBrowser.Server.Implementations.Drawing;
 | 
				
			||||||
using MediaBrowser.Server.Implementations.Dto;
 | 
					using MediaBrowser.Server.Implementations.Dto;
 | 
				
			||||||
@ -488,6 +490,9 @@ namespace MediaBrowser.ServerApplication
 | 
				
			|||||||
            var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
 | 
					            var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
 | 
				
			||||||
            RegisterSingleInstance<IAppThemeManager>(appThemeManager);
 | 
					            RegisterSingleInstance<IAppThemeManager>(appThemeManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);
 | 
				
			||||||
 | 
					            RegisterSingleInstance<ICollectionManager>(collectionManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager);
 | 
					            LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager);
 | 
				
			||||||
            RegisterSingleInstance(LiveTvManager);
 | 
					            RegisterSingleInstance(LiveTvManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 | 
					    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 | 
				
			||||||
      <dependentAssembly>
 | 
					      <dependentAssembly>
 | 
				
			||||||
        <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
 | 
					        <assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
 | 
				
			||||||
        <bindingRedirect oldVersion="0.0.0.0-1.0.89.0" newVersion="1.0.89.0" />
 | 
					        <bindingRedirect oldVersion="0.0.0.0-1.0.91.0" newVersion="1.0.91.0" />
 | 
				
			||||||
      </dependentAssembly>
 | 
					      </dependentAssembly>
 | 
				
			||||||
    </assemblyBinding>
 | 
					    </assemblyBinding>
 | 
				
			||||||
  </runtime>
 | 
					  </runtime>
 | 
				
			||||||
 | 
				
			|||||||
@ -480,6 +480,7 @@ namespace MediaBrowser.WebDashboard.Api
 | 
				
			|||||||
                                      "dashboardinfo.js",
 | 
					                                      "dashboardinfo.js",
 | 
				
			||||||
                                      "dashboardpage.js",
 | 
					                                      "dashboardpage.js",
 | 
				
			||||||
                                      "directorybrowser.js",
 | 
					                                      "directorybrowser.js",
 | 
				
			||||||
 | 
					                                      "editcollectionitems.js",
 | 
				
			||||||
                                      "edititemmetadata.js",
 | 
					                                      "edititemmetadata.js",
 | 
				
			||||||
                                      "edititempeople.js",
 | 
					                                      "edititempeople.js",
 | 
				
			||||||
                                      "edititemimages.js",
 | 
					                                      "edititemimages.js",
 | 
				
			||||||
 | 
				
			|||||||
@ -213,6 +213,9 @@
 | 
				
			|||||||
    <Content Include="dashboard-ui\dashboardinfopage.html">
 | 
					    <Content Include="dashboard-ui\dashboardinfopage.html">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
 | 
					    <Content Include="dashboard-ui\editcollectionitems.html">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </Content>
 | 
				
			||||||
    <Content Include="dashboard-ui\encodingsettings.html">
 | 
					    <Content Include="dashboard-ui\encodingsettings.html">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
@ -261,7 +264,7 @@
 | 
				
			|||||||
    <Content Include="dashboard-ui\allusersettings.html">
 | 
					    <Content Include="dashboard-ui\allusersettings.html">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
    <Content Include="dashboard-ui\boxsets.html">
 | 
					    <Content Include="dashboard-ui\collections.html">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
    <Content Include="dashboard-ui\css\images\clients\mbkinect.png">
 | 
					    <Content Include="dashboard-ui\css\images\clients\mbkinect.png">
 | 
				
			||||||
@ -480,6 +483,9 @@
 | 
				
			|||||||
    <Content Include="dashboard-ui\scripts\dashboardinfo.js">
 | 
					    <Content Include="dashboard-ui\scripts\dashboardinfo.js">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
 | 
					    <Content Include="dashboard-ui\scripts\editcollectionitems.js">
 | 
				
			||||||
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
 | 
					    </Content>
 | 
				
			||||||
    <Content Include="dashboard-ui\scripts\encodingsettings.js">
 | 
					    <Content Include="dashboard-ui\scripts\encodingsettings.js">
 | 
				
			||||||
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
					      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 | 
				
			||||||
    </Content>
 | 
					    </Content>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user