fixes #715 - Support creating/editing collections (boxsets) in web client #715

This commit is contained in:
Luke Pulverenti 2014-03-07 13:48:55 -05:00
parent e00985d07c
commit 546acf0ebb
11 changed files with 184 additions and 20 deletions

View File

@ -134,7 +134,7 @@ namespace MediaBrowser.Api
IncludeStudios = request.IncludeStudios, IncludeStudios = request.IncludeStudios,
StartIndex = request.StartIndex, StartIndex = request.StartIndex,
UserId = request.UserId, UserId = request.UserId,
IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',') IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray()
}).ConfigureAwait(false); }).ConfigureAwait(false);

View File

@ -745,9 +745,9 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>(); var list = new List<BaseItem>();
AddChildrenToList(user, includeLinkedChildren, list, false, null); var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, null);
return list; return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
} }
/// <summary> /// <summary>

View File

@ -22,8 +22,8 @@ namespace MediaBrowser.Controller.Entities
public enum LinkedChildType public enum LinkedChildType
{ {
Manual = 1, Manual = 0,
Shortcut = 2 Shortcut = 1
} }
public class LinkedChildComparer : IEqualityComparer<LinkedChild> public class LinkedChildComparer : IEqualityComparer<LinkedChild>
@ -39,7 +39,7 @@ namespace MediaBrowser.Controller.Entities
public int GetHashCode(LinkedChild obj) public int GetHashCode(LinkedChild obj)
{ {
return (obj.Path + obj.Type.ToString()).GetHashCode(); return (obj.Path + obj.Type).GetHashCode();
} }
} }
} }

View File

@ -51,9 +51,8 @@ namespace MediaBrowser.Controller.Library
/// Refreshes metadata for each user /// Refreshes metadata for each user
/// </summary> /// </summary>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task RefreshUsersMetadata(CancellationToken cancellationToken, bool force = false); Task RefreshUsersMetadata(CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Renames the user. /// Renames the user.

View File

@ -1,5 +1,6 @@
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
@ -37,6 +38,15 @@ namespace MediaBrowser.Providers.BoxSets
protected override void MergeData(BoxSet source, BoxSet target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) protected override void MergeData(BoxSet source, BoxSet target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
{ {
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
if (mergeMetadataSettings)
{
var list = source.LinkedChildren.ToList();
list.AddRange(target.LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut));
target.LinkedChildren = list;
}
} }
protected override ItemUpdateType BeforeSave(BoxSet item) protected override ItemUpdateType BeforeSave(BoxSet item)

View File

@ -0,0 +1,129 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
namespace MediaBrowser.Providers.BoxSets
{
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
{
private readonly CultureInfo UsCulture = new CultureInfo("en-US");
public BoxSetXmlParser(ILogger logger)
: base(logger)
{
}
protected override void FetchDataFromXmlNode(XmlReader reader, BoxSet item)
{
switch (reader.Name)
{
case "CollectionItems":
using (var subReader = reader.ReadSubtree())
{
FetchFromCollectionItemsNode(subReader, item);
}
break;
default:
base.FetchDataFromXmlNode(reader, item);
break;
}
}
private void FetchFromCollectionItemsNode(XmlReader reader, BoxSet item)
{
reader.MoveToContent();
var list = new List<LinkedChild>();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "CollectionItem":
{
using (var subReader = reader.ReadSubtree())
{
var child = GetLinkedChild(subReader);
if (child != null)
{
list.Add(child);
}
}
break;
}
default:
reader.Skip();
break;
}
}
}
item.LinkedChildren = list;
}
private LinkedChild GetLinkedChild(XmlReader reader)
{
reader.MoveToContent();
var linkedItem = new LinkedChild
{
Type = LinkedChildType.Manual
};
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Name":
{
linkedItem.ItemName = reader.ReadElementContentAsString();
break;
}
case "Type":
{
linkedItem.ItemType = reader.ReadElementContentAsString();
break;
}
case "Year":
{
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
int rval;
if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
{
linkedItem.ItemYear = rval;
}
}
break;
}
default:
reader.Skip();
break;
}
}
}
return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem;
}
}
}

View File

@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.BoxSets
protected override void Fetch(LocalMetadataResult<BoxSet> result, string path, CancellationToken cancellationToken) protected override void Fetch(LocalMetadataResult<BoxSet> result, string path, CancellationToken cancellationToken)
{ {
new BaseItemXmlParser<BoxSet>(_logger).Fetch(result.Item, path, cancellationToken); new BoxSetXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
} }
protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService) protected override FileInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

View File

@ -75,6 +75,7 @@
<Compile Include="All\LocalImageProvider.cs" /> <Compile Include="All\LocalImageProvider.cs" />
<Compile Include="Books\BookMetadataService.cs" /> <Compile Include="Books\BookMetadataService.cs" />
<Compile Include="BoxSets\BoxSetMetadataService.cs" /> <Compile Include="BoxSets\BoxSetMetadataService.cs" />
<Compile Include="BoxSets\BoxSetXmlParser.cs" />
<Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" /> <Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" />
<Compile Include="BoxSets\MovieDbBoxSetProvider.cs" /> <Compile Include="BoxSets\MovieDbBoxSetProvider.cs" />
<Compile Include="Folders\CollectionFolderImageProvider.cs" /> <Compile Include="Folders\CollectionFolderImageProvider.cs" />

View File

@ -148,9 +148,39 @@ namespace MediaBrowser.Server.Implementations.Collections
list.Add(child); list.Add(child);
} }
foreach (var child in list) var shortcutFiles = Directory
.EnumerateFiles(collection.Path, "*", SearchOption.TopDirectoryOnly)
.Where(i => _fileSystem.IsShortcut(i))
.ToList();
var shortcutFilesToDelete = list.Where(child => !string.IsNullOrWhiteSpace(child.Path) && child.Type == LinkedChildType.Shortcut)
.Select(child => shortcutFiles.FirstOrDefault(i => string.Equals(child.Path, _fileSystem.ResolveShortcut(i), StringComparison.OrdinalIgnoreCase)))
.Where(i => !string.IsNullOrWhiteSpace(i))
.ToList();
foreach (var file in shortcutFilesToDelete)
{ {
collection.LinkedChildren.Remove(child); _iLibraryMonitor.ReportFileSystemChangeBeginning(file);
}
try
{
foreach (var file in shortcutFilesToDelete)
{
File.Delete(file);
}
foreach (var child in list)
{
collection.LinkedChildren.Remove(child);
}
}
finally
{
foreach (var file in shortcutFilesToDelete)
{
_iLibraryMonitor.ReportFileSystemChangeComplete(file, false);
}
} }
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);

View File

@ -189,15 +189,10 @@ namespace MediaBrowser.Server.Implementations.Library
/// Refreshes metadata for each user /// Refreshes metadata for each user
/// </summary> /// </summary>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="force">if set to <c>true</c> [force].</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task RefreshUsersMetadata(CancellationToken cancellationToken, bool force = false) public Task RefreshUsersMetadata(CancellationToken cancellationToken)
{ {
var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken)).ToList();
{
ReplaceAllMetadata = force
}, cancellationToken)).ToList();
return Task.WhenAll(tasks); return Task.WhenAll(tasks);
} }

View File

@ -582,8 +582,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
.Select(i => _libraryManager.GetGenre(i)) .Select(i => _libraryManager.GetGenre(i))
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
programs = programList.OrderByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres)) programs = programList.OrderBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
.ThenBy(i => i.HasImage(ImageType.Primary) ? 0 : 1) .ThenByDescending(i => GetRecommendationScore(i, user.Id, serviceName, genres))
.ThenBy(i => i.StartDate); .ThenBy(i => i.StartDate);
if (query.Limit.HasValue) if (query.Limit.HasValue)