Pārlūkot izejas kodu

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

Luke Pulverenti 11 gadi atpakaļ
vecāks
revīzija
546acf0ebb

+ 1 - 1
MediaBrowser.Api/SearchService.cs

@@ -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);
 
 

+ 2 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -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>

+ 3 - 3
MediaBrowser.Controller/Entities/LinkedChild.cs

@@ -22,8 +22,8 @@ namespace MediaBrowser.Controller.Entities
 
 
     public enum LinkedChildType
     public enum LinkedChildType
     {
     {
-        Manual = 1,
-        Shortcut = 2
+        Manual = 0,
+        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();
         }
         }
     }
     }
 }
 }

+ 1 - 2
MediaBrowser.Controller/Library/IUserManager.cs

@@ -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.

+ 10 - 0
MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs

@@ -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)

+ 129 - 0
MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs

@@ -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;
+        }
+    }
+}

+ 1 - 1
MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs

@@ -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)

+ 1 - 0
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -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" />

+ 32 - 2
MediaBrowser.Server.Implementations/Collections/CollectionManager.cs

@@ -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)
+            {
+                _iLibraryMonitor.ReportFileSystemChangeBeginning(file);
+            }
+
+            try
             {
             {
-                collection.LinkedChildren.Remove(child);
+                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);

+ 2 - 7
MediaBrowser.Server.Implementations/Library/UserManager.cs

@@ -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
-            {
-                ReplaceAllMetadata = force
-
-            }, cancellationToken)).ToList();
+            var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken)).ToList();
 
 
             return Task.WhenAll(tasks);
             return Task.WhenAll(tasks);
         }
         }

+ 2 - 2
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -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))
-                .ThenBy(i => i.HasImage(ImageType.Primary) ? 0 : 1)
+            programs = programList.OrderBy(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)