diff options
| author | LukePulverenti <luke.pulverenti@gmail.com> | 2013-03-09 23:22:36 -0500 |
|---|---|---|
| committer | LukePulverenti <luke.pulverenti@gmail.com> | 2013-03-09 23:22:36 -0500 |
| commit | 31d079f1baea895b5cb0f1a737140ab94dc9a4fe (patch) | |
| tree | 1ed702bbed6edb1cc7f505c92e42a4263b1f8ed3 | |
| parent | 913cb3c564e58dd440dbf3af81f38aad68c1ac2a (diff) | |
unified the two sorting api's
30 files changed, 676 insertions, 660 deletions
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 9aa4203a9..a02c3c012 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -82,12 +81,6 @@ namespace MediaBrowser.Api.UserLibrary public string IndexBy { get; set; } /// <summary> - /// The dynamic, localized sort function name - /// </summary> - /// <value>The dynamic sort by.</value> - public string DynamicSortBy { get; set; } - - /// <summary> /// What to sort the results by /// </summary> /// <value>The sort by.</value> @@ -254,7 +247,7 @@ namespace MediaBrowser.Api.UserLibrary return ((Folder)item).GetRecursiveChildren(user); } - return ((Folder)item).GetChildren(user, request.IndexBy, request.DynamicSortBy, GetSortOrder(request)); + return ((Folder)item).GetChildren(user, request.IndexBy); } /// <summary> @@ -266,58 +259,9 @@ namespace MediaBrowser.Api.UserLibrary /// <returns>IEnumerable{BaseItem}.</returns> private IEnumerable<BaseItem> ApplySortOrder(GetItems request, IEnumerable<BaseItem> items, User user) { - var isFirst = true; - var descending = (GetSortOrder(request) ?? SortOrder.Ascending) == SortOrder.Descending; + var orderBy = GetOrderBy(request).ToArray(); - IOrderedEnumerable<BaseItem> orderedItems = null; - - foreach (var orderBy in GetOrderBy(request).Select(o => GetComparer(o, user))) - { - if (isFirst) - { - orderedItems = descending ? items.OrderByDescending(i => i, orderBy) : items.OrderBy(i => i, orderBy); - } - else - { - orderedItems = descending ? orderedItems.ThenByDescending(i => i, orderBy) : orderedItems.ThenBy(i => i, orderBy); - } - - isFirst = false; - } - - return orderedItems ?? items; - } - - /// <summary> - /// Gets the comparer. - /// </summary> - /// <param name="sortBy">The sort by.</param> - /// <param name="user">The user.</param> - /// <returns>IComparer{BaseItem}.</returns> - /// <exception cref="System.ArgumentException"></exception> - private IComparer<BaseItem> GetComparer(ItemSortBy sortBy, User user) - { - switch (sortBy) - { - case ItemSortBy.Album: - return new AlbumComparer(); - case ItemSortBy.AlbumArtist: - return new AlbumArtistComparer(); - case ItemSortBy.Artist: - return new ArtistComparer(); - case ItemSortBy.Random: - return new RandomComparer(); - case ItemSortBy.DateCreated: - return new DateCreatedComparer(); - case ItemSortBy.SortName: - return new SortNameComparer(); - case ItemSortBy.PremiereDate: - return new PremiereDateComparer(); - case ItemSortBy.DatePlayed: - return new DatePlayedComparer { User = user }; - default: - throw new ArgumentException(); - } + return orderBy.Length == 0 ? items : _libraryManager.Sort(items, user, orderBy, GetSortOrder(request) ?? SortOrder.Ascending); } /// <summary> @@ -575,16 +519,16 @@ namespace MediaBrowser.Api.UserLibrary /// </summary> /// <param name="request">The request.</param> /// <returns>IEnumerable{ItemSortBy}.</returns> - private IEnumerable<ItemSortBy> GetOrderBy(GetItems request) + private IEnumerable<string> GetOrderBy(GetItems request) { var val = request.SortBy; if (string.IsNullOrEmpty(val)) { - return new ItemSortBy[] { }; + return new string[] { }; } - return val.Split(',').Select(v => (ItemSortBy)Enum.Parse(typeof(ItemSortBy), v, true)); + return val.Split(','); } /// <summary> @@ -621,201 +565,4 @@ namespace MediaBrowser.Api.UserLibrary return x.DateCreated.CompareTo(y.DateCreated); } } - - /// <summary> - /// Class RandomComparer - /// </summary> - public class RandomComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return Guid.NewGuid().CompareTo(Guid.NewGuid()); - } - } - - /// <summary> - /// Class SortNameComparer - /// </summary> - public class SortNameComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); - } - } - - /// <summary> - /// Class AlbumArtistComparer - /// </summary> - public class AlbumArtistComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as Audio; - - return audio == null ? string.Empty : audio.AlbumArtist; - } - } - - /// <summary> - /// Class AlbumComparer - /// </summary> - public class AlbumComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as Audio; - - return audio == null ? string.Empty : audio.Album; - } - } - - /// <summary> - /// Class ArtistComparer - /// </summary> - public class ArtistComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private string GetValue(BaseItem x) - { - var audio = x as Audio; - - return audio == null ? string.Empty : audio.Artist; - } - } - - /// <summary> - /// Class PremiereDateComparer - /// </summary> - public class PremiereDateComparer : IComparer<BaseItem> - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - if (x.PremiereDate.HasValue) - { - return x.PremiereDate.Value; - } - - if (x.ProductionYear.HasValue) - { - return new DateTime(x.ProductionYear.Value, 1, 1, 0, 0, 0, DateTimeKind.Utc); - } - return DateTime.MaxValue; - } - } - - /// <summary> - /// Class DatePlayedComparer - /// </summary> - public class DatePlayedComparer : IComparer<BaseItem> - { - /// <summary> - /// Gets or sets the user. - /// </summary> - /// <value>The user.</value> - public User User { get; set; } - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetDate(x).CompareTo(GetDate(y)); - } - - /// <summary> - /// Gets the date. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>DateTime.</returns> - private DateTime GetDate(BaseItem x) - { - var userdata = x.GetUserData(User, false); - - if (userdata != null && userdata.LastPlayedDate.HasValue) - { - return userdata.LastPlayedDate.Value; - } - - return DateTime.MinValue; - } - } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index c6f479029..ef34742df 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -13,7 +13,6 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using SortOrder = MediaBrowser.Controller.Sorting.SortOrder; namespace MediaBrowser.Controller.Entities { @@ -177,63 +176,6 @@ namespace MediaBrowser.Controller.Entities } } - #region Sorting - - /// <summary> - /// The _sort by options - /// </summary> - private Dictionary<string, IComparer<BaseItem>> _sortByOptions; - /// <summary> - /// Dictionary of sort options - consists of a display value (localized) and an IComparer of BaseItem - /// </summary> - /// <value>The sort by options.</value> - [IgnoreDataMember] - public Dictionary<string, IComparer<BaseItem>> SortByOptions - { - get { return _sortByOptions ?? (_sortByOptions = GetSortByOptions()); } - } - - /// <summary> - /// Returns the valid set of sort by options for this folder type. - /// Override or extend to modify. - /// </summary> - /// <returns>Dictionary{System.StringIComparer{BaseItem}}.</returns> - protected virtual Dictionary<string, IComparer<BaseItem>> GetSortByOptions() - { - return new Dictionary<string, IComparer<BaseItem>> { - {LocalizedStrings.Instance.GetString("NameDispPref"), new BaseItemComparer(SortOrder.Name, Logger)}, - {LocalizedStrings.Instance.GetString("DateDispPref"), new BaseItemComparer(SortOrder.Date, Logger)}, - {LocalizedStrings.Instance.GetString("RatingDispPref"), new BaseItemComparer(SortOrder.Rating, Logger)}, - {LocalizedStrings.Instance.GetString("RuntimeDispPref"), new BaseItemComparer(SortOrder.Runtime, Logger)}, - {LocalizedStrings.Instance.GetString("YearDispPref"), new BaseItemComparer(SortOrder.Year, Logger)} - }; - - } - - /// <summary> - /// Get a sorting comparer by name - /// </summary> - /// <param name="name">The name.</param> - /// <returns>IComparer{BaseItem}.</returns> - private IComparer<BaseItem> GetSortingFunction(string name) - { - IComparer<BaseItem> sorting; - SortByOptions.TryGetValue(name ?? "", out sorting); - return sorting ?? new BaseItemComparer(SortOrder.Name, Logger); - } - - /// <summary> - /// Get the list of sort by choices for this folder (localized). - /// </summary> - /// <value>The sort by option strings.</value> - [IgnoreDataMember] - public IEnumerable<string> SortByOptionStrings - { - get { return SortByOptions.Keys; } - } - - #endregion - #region Indexing /// <summary> @@ -877,11 +819,9 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="user">The user.</param> /// <param name="indexBy">The index by.</param> - /// <param name="sortBy">The sort by.</param> - /// <param name="sortOrder">The sort order.</param> /// <returns>IEnumerable{BaseItem}.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public virtual IEnumerable<BaseItem> GetChildren(User user, string indexBy = null, string sortBy = null, Model.Entities.SortOrder? sortOrder = null) + public virtual IEnumerable<BaseItem> GetChildren(User user, string indexBy = null) { if (user == null) { @@ -889,7 +829,7 @@ namespace MediaBrowser.Controller.Entities } //the true root should return our users root folder children - if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, indexBy, sortBy, sortOrder); + if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, indexBy); IEnumerable<BaseItem> result = null; @@ -904,14 +844,7 @@ namespace MediaBrowser.Controller.Entities result = ActualChildren.Where(c => c.IsVisible(user)); } - if (string.IsNullOrEmpty(sortBy)) - { - return result; - } - - return sortOrder.HasValue && sortOrder.Value == Model.Entities.SortOrder.Descending - ? result.OrderByDescending(i => i, GetSortingFunction(sortBy)) - : result.OrderBy(i => i, GetSortingFunction(sortBy)); + return result; } /// <summary> diff --git a/MediaBrowser.Controller/Library/DtoBuilder.cs b/MediaBrowser.Controller/Library/DtoBuilder.cs index 92a15b117..bdaa51b6c 100644 --- a/MediaBrowser.Controller/Library/DtoBuilder.cs +++ b/MediaBrowser.Controller/Library/DtoBuilder.cs @@ -373,11 +373,6 @@ namespace MediaBrowser.Controller.Library { dto.IndexOptions = folder.IndexByOptionStrings.ToArray(); } - - if (fields.Contains(ItemFields.SortOptions)) - { - dto.SortOptions = folder.SortByOptionStrings.ToArray(); - } } // Add audio info diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 3f1930209..40131b6d2 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; @@ -158,7 +159,19 @@ namespace MediaBrowser.Controller.Library /// <param name="pluginFolders">The plugin folders.</param> /// <param name="resolvers">The resolvers.</param> /// <param name="introProviders">The intro providers.</param> + /// <param name="itemComparers">The item comparers.</param> void AddParts(IEnumerable<IResolverIgnoreRule> rules, IEnumerable<IVirtualFolderCreator> pluginFolders, - IEnumerable<IItemResolver> resolvers, IEnumerable<IIntroProvider> introProviders); + IEnumerable<IItemResolver> resolvers, IEnumerable<IIntroProvider> introProviders, IEnumerable<IBaseItemComparer> itemComparers); + + /// <summary> + /// Sorts the specified items. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="user">The user.</param> + /// <param name="sortBy">The sort by.</param> + /// <param name="sortOrder">The sort order.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, + SortOrder sortOrder); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5ae6cccac..9b7529023 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -185,8 +185,8 @@ <Compile Include="Providers\FolderProviderFromXml.cs" /> <Compile Include="Providers\ImageFromMediaLocationProvider.cs" /> <Compile Include="Providers\MediaInfo\FFProbeVideoInfoProvider.cs" /> - <Compile Include="Sorting\BaseItemComparer.cs" /> - <Compile Include="Sorting\SortOrder.cs" /> + <Compile Include="Sorting\IBaseItemComparer.cs" /> + <Compile Include="Sorting\IUserBaseItemComparer.cs" /> <Compile Include="Updates\IInstallationManager.cs" /> <Compile Include="Weather\IWeatherProvider.cs" /> <Compile Include="Providers\BaseItemXmlParser.cs" /> diff --git a/MediaBrowser.Controller/Sorting/BaseItemComparer.cs b/MediaBrowser.Controller/Sorting/BaseItemComparer.cs deleted file mode 100644 index 94c16775d..000000000 --- a/MediaBrowser.Controller/Sorting/BaseItemComparer.cs +++ /dev/null @@ -1,248 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Sorting { - /// <summary> - /// Class BaseItemComparer - /// </summary> - public class BaseItemComparer : IComparer<BaseItem> { - /// <summary> - /// The _order - /// </summary> - private readonly SortOrder _order; - /// <summary> - /// The _property name - /// </summary> - private readonly string _propertyName; - /// <summary> - /// The _compare culture - /// </summary> - private readonly StringComparison _compareCulture = StringComparison.CurrentCultureIgnoreCase; - - /// <summary> - /// Gets or sets the logger. - /// </summary> - /// <value>The logger.</value> - private ILogger Logger { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. - /// </summary> - /// <param name="order">The order.</param> - /// <param name="logger">The logger.</param> - public BaseItemComparer(SortOrder order, ILogger logger) { - _order = order; - Logger = logger; - } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. - /// </summary> - /// <param name="order">The order.</param> - /// <param name="compare">The compare.</param> - /// <param name="logger">The logger.</param> - public BaseItemComparer(SortOrder order, StringComparison compare, ILogger logger) - { - _order = order; - _compareCulture = compare; - Logger = logger; - } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. - /// </summary> - /// <param name="property">The property.</param> - /// <param name="logger">The logger.</param> - public BaseItemComparer(string property, ILogger logger) - { - _order = SortOrder.Custom; - _propertyName = property; - Logger = logger; - } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. - /// </summary> - /// <param name="property">The property.</param> - /// <param name="compare">The compare.</param> - /// <param name="logger">The logger.</param> - public BaseItemComparer(string property, StringComparison compare, ILogger logger) - { - _order = SortOrder.Custom; - _propertyName = property; - _compareCulture = compare; - Logger = logger; - } - - #region IComparer<BaseItem> Members - - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) { - int compare = 0; - - switch (_order) { - - case SortOrder.Date: - compare = -x.DateCreated.CompareTo(y.DateCreated); - break; - - case SortOrder.Year: - - var xProductionYear = x.ProductionYear ?? 0; - var yProductionYear = y.ProductionYear ?? 0; - - - compare = yProductionYear.CompareTo(xProductionYear); - break; - - case SortOrder.Rating: - - var xRating = x.CommunityRating ?? 0; - var yRating = y.CommunityRating ?? 0; - - compare = yRating.CompareTo(xRating); - break; - - case SortOrder.Runtime: - var xRuntime = x.RunTimeTicks ?? 0; - var yRuntime = y.RunTimeTicks ?? 0; - - compare = xRuntime.CompareTo(yRuntime); - break; - - case SortOrder.Custom: - - Logger.Debug("Sorting on custom field " + _propertyName); - var yProp = y.GetType().GetProperty(_propertyName); - var xProp = x.GetType().GetProperty(_propertyName); - if (yProp == null || xProp == null) break; - var yVal = yProp.GetValue(y, null); - var xVal = xProp.GetValue(x,null); - if (yVal == null && xVal == null) break; - if (yVal == null) return 1; - if (xVal == null) return -1; - compare = String.Compare(xVal.ToString(), yVal.ToString(),_compareCulture); - break; - - default: - compare = 0; - break; - } - - if (compare == 0) { - - var name1 = x.SortName ?? x.Name ?? ""; - var name2 = y.SortName ?? y.Name ?? ""; - - //if (Config.Instance.EnableAlphanumericSorting) - compare = AlphaNumericCompare(name1, name2,_compareCulture); - //else - // compare = String.Compare(name1,name2,_compareCulture); - } - - return compare; - } - - - #endregion - - /// <summary> - /// Alphas the numeric compare. - /// </summary> - /// <param name="s1">The s1.</param> - /// <param name="s2">The s2.</param> - /// <param name="compareCulture">The compare culture.</param> - /// <returns>System.Int32.</returns> - private int AlphaNumericCompare(string s1, string s2, StringComparison compareCulture) { - // http://dotnetperls.com/Content/Alphanumeric-Sorting.aspx - - int len1 = s1.Length; - int len2 = s2.Length; - int marker1 = 0; - int marker2 = 0; - - // Walk through two the strings with two markers. - while (marker1 < len1 && marker2 < len2) { - char ch1 = s1[marker1]; - char ch2 = s2[marker2]; - - // Some buffers we can build up characters in for each chunk. - var space1 = new char[len1]; - var loc1 = 0; - var space2 = new char[len2]; - var loc2 = 0; - - // Walk through all following characters that are digits or - // characters in BOTH strings starting at the appropriate marker. - // Collect char arrays. - do { - space1[loc1++] = ch1; - marker1++; - - if (marker1 < len1) { - ch1 = s1[marker1]; - } else { - break; - } - } while (char.IsDigit(ch1) == char.IsDigit(space1[0])); - - do { - space2[loc2++] = ch2; - marker2++; - - if (marker2 < len2) { - ch2 = s2[marker2]; - } else { - break; - } - } while (char.IsDigit(ch2) == char.IsDigit(space2[0])); - - // If we have collected numbers, compare them numerically. - // Otherwise, if we have strings, compare them alphabetically. - var str1 = new string(space1); - var str2 = new string(space2); - - var result = 0; - - //biggest int - 2147483647 - if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]) /*&& str1.Length < 10 && str2.Length < 10*/) //this assumed the entire string was a number... - { - int thisNumericChunk; - var isValid = false; - - if (int.TryParse(str1.Substring(0, str1.Length > 9 ? 10 : str1.Length), out thisNumericChunk)) - { - int thatNumericChunk; - - if (int.TryParse(str2.Substring(0, str2.Length > 9 ? 10 : str2.Length), out thatNumericChunk)) - { - isValid = true; - result = thisNumericChunk.CompareTo(thatNumericChunk); - } - } - - if (!isValid) - { - Logger.Error("Error comparing numeric strings: " + str1 + "/" + str2); - result = String.Compare(str1, str2, compareCulture); - } - - } else { - result = String.Compare(str1,str2,compareCulture); - } - - if (result != 0) { - return result; - } - } - return len1 - len2; - } - } -} diff --git a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs new file mode 100644 index 000000000..6d0b95bcb --- /dev/null +++ b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs @@ -0,0 +1,17 @@ +using MediaBrowser.Controller.Entities; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Sorting +{ + /// <summary> + /// Interface IBaseItemComparer + /// </summary> + public interface IBaseItemComparer : IComparer<BaseItem> + { + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + string Name { get; } + } +} diff --git a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs new file mode 100644 index 000000000..b9da1f6a6 --- /dev/null +++ b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Sorting +{ + /// <summary> + /// Represents a BaseItem comparer that requires a User to perform it's comparison + /// </summary> + public interface IUserBaseItemComparer : IBaseItemComparer + { + /// <summary> + /// Gets or sets the user. + /// </summary> + /// <value>The user.</value> + User User { get; set; } + } +} diff --git a/MediaBrowser.Controller/Sorting/SortOrder.cs b/MediaBrowser.Controller/Sorting/SortOrder.cs deleted file mode 100644 index 3152ac67e..000000000 --- a/MediaBrowser.Controller/Sorting/SortOrder.cs +++ /dev/null @@ -1,33 +0,0 @@ - -namespace MediaBrowser.Controller.Sorting { - /// <summary> - /// Enum SortOrder - /// </summary> - public enum SortOrder { - - /// <summary> - /// Sort by name - /// </summary> - Name, - /// <summary> - /// Sort by date added to the library - /// </summary> - Date, - /// <summary> - /// Sort by community rating - /// </summary> - Rating, - /// <summary> - /// Sort by runtime - /// </summary> - Runtime, - /// <summary> - /// Sort by year - /// </summary> - Year, - /// <summary> - /// Custom sort order added by plugins - /// </summary> - Custom - } -} diff --git a/MediaBrowser.Model/DTO/BaseItemDto.cs b/MediaBrowser.Model/DTO/BaseItemDto.cs index 971b0bde7..b1d3f83c2 100644 --- a/MediaBrowser.Model/DTO/BaseItemDto.cs +++ b/MediaBrowser.Model/DTO/BaseItemDto.cs @@ -316,13 +316,6 @@ namespace MediaBrowser.Model.Dto public List<DayOfWeek> AirDays { get; set; } /// <summary> - /// Gets or sets the sort options. - /// </summary> - /// <value>The sort options.</value> - [ProtoMember(53)] - public string[] SortOptions { get; set; } - - /// <summary> /// Gets or sets the index options. /// </summary> /// <value>The index options.</value> diff --git a/MediaBrowser.Model/DTO/ItemFields.cs b/MediaBrowser.Model/DTO/ItemFields.cs index a24c8a8f0..981afe894 100644 --- a/MediaBrowser.Model/DTO/ItemFields.cs +++ b/MediaBrowser.Model/DTO/ItemFields.cs @@ -87,11 +87,6 @@ namespace MediaBrowser.Model.Dto SortName, /// <summary> - /// The fields that the server supports sorting on - /// </summary> - SortOptions, - - /// <summary> /// The studios of the item /// </summary> Studios, diff --git a/MediaBrowser.Model/DTO/ItemQuery.cs b/MediaBrowser.Model/DTO/ItemQuery.cs index 6d64a093b..085a872b1 100644 --- a/MediaBrowser.Model/DTO/ItemQuery.cs +++ b/MediaBrowser.Model/DTO/ItemQuery.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Model.Dto /// What to sort the results by /// </summary> /// <value>The sort by.</value> - public ItemSortBy[] SortBy { get; set; } + public string[] SortBy { get; set; } /// <summary> /// The sort order to return results with @@ -117,12 +117,6 @@ namespace MediaBrowser.Model.Dto public string IndexBy { get; set; } /// <summary> - /// The dynamic, localized sort function name - /// </summary> - /// <value>The dynamic sort by.</value> - public string DynamicSortBy { get; set; } - - /// <summary> /// Gets or sets the image types. /// </summary> /// <value>The image types.</value> diff --git a/MediaBrowser.Model/DTO/ItemSortBy.cs b/MediaBrowser.Model/DTO/ItemSortBy.cs index 30cd1c3a4..141690a55 100644 --- a/MediaBrowser.Model/DTO/ItemSortBy.cs +++ b/MediaBrowser.Model/DTO/ItemSortBy.cs @@ -2,41 +2,53 @@ namespace MediaBrowser.Model.Dto { /// <summary> - /// Enum ItemSortBy + /// These represent sort orders that are known by the core /// </summary> - public enum ItemSortBy + public static class ItemSortBy { /// <summary> /// The album /// </summary> - Album, + public const string Album = "Album"; /// <summary> /// The album artist /// </summary> - AlbumArtist, + public const string AlbumArtist = "AlbumArtist"; /// <summary> /// The artist /// </summary> - Artist, + public const string Artist = "Artist"; /// <summary> /// The date created /// </summary> - DateCreated, + public const string DateCreated = "DateCreated"; /// <summary> /// The date played /// </summary> - DatePlayed, + public const string DatePlayed = "DatePlayed"; /// <summary> /// The premiere date /// </summary> - PremiereDate, + public const string PremiereDate = "PremiereDate"; /// <summary> /// The sort name /// </summary> - SortName, + public const string SortName = "SortName"; /// <summary> /// The random /// </summary> - Random + public const string Random = "Random"; + /// <summary> + /// The runtime + /// </summary> + public const string Runtime = "Runtime"; + /// <summary> + /// The community rating + /// </summary> + public const string CommunityRating = "CommunityRating"; + /// <summary> + /// The production year + /// </summary> + public const string ProductionYear = "ProductionYear"; } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 78ada1431..6cd46a310 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.ScheduledTasks; +using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations.Library.Resolvers; @@ -22,6 +23,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using SortOrder = MediaBrowser.Model.Entities.SortOrder; namespace MediaBrowser.Server.Implementations.Library { @@ -54,6 +56,12 @@ namespace MediaBrowser.Server.Implementations.Library /// <value>The entity resolvers enumerable.</value> private IEnumerable<IItemResolver> EntityResolvers { get; set; } + /// <summary> + /// Gets or sets the comparers. + /// </summary> + /// <value>The comparers.</value> + private IEnumerable<IBaseItemComparer> Comparers { get; set; } + #region LibraryChanged Event /// <summary> /// Fires whenever any validation routine adds or removes items. The added and removed items are properties of the args. @@ -124,12 +132,14 @@ namespace MediaBrowser.Server.Implementations.Library /// <param name="pluginFolders">The plugin folders.</param> /// <param name="resolvers">The resolvers.</param> /// <param name="introProviders">The intro providers.</param> - public void AddParts(IEnumerable<IResolverIgnoreRule> rules, IEnumerable<IVirtualFolderCreator> pluginFolders, IEnumerable<IItemResolver> resolvers, IEnumerable<IIntroProvider> introProviders) + /// <param name="itemComparers">The item comparers.</param> + public void AddParts(IEnumerable<IResolverIgnoreRule> rules, IEnumerable<IVirtualFolderCreator> pluginFolders, IEnumerable<IItemResolver> resolvers, IEnumerable<IIntroProvider> introProviders, IEnumerable<IBaseItemComparer> itemComparers) { EntityResolutionIgnoreRules = rules; PluginFolderCreators = pluginFolders; EntityResolvers = resolvers.OrderBy(i => i.Priority).ToArray(); IntroProviders = introProviders; + Comparers = itemComparers; } /// <summary> @@ -702,5 +712,62 @@ namespace MediaBrowser.Server.Implementations.Library { return IntroProviders.SelectMany(i => i.GetIntros(item, user)); } + + /// <summary> + /// Sorts the specified sort by. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="user">The user.</param> + /// <param name="sortBy">The sort by.</param> + /// <param name="sortOrder">The sort order.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder) + { + var isFirst = true; + + IOrderedEnumerable<BaseItem> orderedItems = null; + + foreach (var orderBy in sortBy.Select(o => GetComparer(o, user)).Where(c => c != null)) + { + if (isFirst) + { + orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, orderBy) : items.OrderBy(i => i, orderBy); + } + else + { + orderedItems = sortOrder == SortOrder.Descending ? orderedItems.ThenByDescending(i => i, orderBy) : orderedItems.ThenBy(i => i, orderBy); + } + + isFirst = false; + } + + return orderedItems ?? items; + } + + /// <summary> + /// Gets the comparer. + /// </summary> + /// <param name="name">The name.</param> + /// <param name="user">The user.</param> + /// <returns>IBaseItemComparer.</returns> + private IBaseItemComparer GetComparer(string name, User user) + { + var comparer = Comparers.FirstOrDefault(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase)); + + if (comparer != null) + { + // If it requires a user, create a new one, and assign the user + if (comparer is IUserBaseItemComparer) + { + var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType()); + + userComparer.User = user; + + return userComparer; + } + } + + return comparer; + } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 0b9f7c7e1..c8a7a2fc1 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -139,6 +139,17 @@ <Compile Include="ServerApplicationPaths.cs" /> <Compile Include="ServerManager\ServerManager.cs" /> <Compile Include="ServerManager\WebSocketConnection.cs" /> + <Compile Include="Sorting\AlbumArtistComparer.cs" /> + <Compile Include="Sorting\AlbumComparer.cs" /> + <Compile Include="Sorting\ArtistComparer.cs" /> + <Compile Include="Sorting\CommunityRatingComparer.cs" /> + <Compile Include="Sorting\DateCreatedComparer.cs" /> + <Compile Include="Sorting\DatePlayedComparer.cs" /> + <Compile Include="Sorting\PremiereDateComparer.cs" /> + <Compile Include="Sorting\ProductionYearComparer.cs" /> + <Compile Include="Sorting\RandomComparer.cs" /> + <Compile Include="Sorting\RuntimeComparer.cs" /> + <Compile Include="Sorting\SortNameComparer.cs" /> <Compile Include="Sqlite\SQLiteDisplayPreferencesRepository.cs" /> <Compile Include="Sqlite\SQLiteExtensions.cs" /> <Compile Include="Sqlite\SQLiteItemRepository.cs" /> diff --git a/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs new file mode 100644 index 000000000..e045cdfc8 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/AlbumArtistComparer.cs @@ -0,0 +1,46 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class AlbumArtistComparer + /// </summary> + public class AlbumArtistComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); + } + + /// <summary> + /// Gets the value. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>System.String.</returns> + private string GetValue(BaseItem x) + { + var audio = x as Audio; + + return audio == null ? string.Empty : audio.AlbumArtist; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.AlbumArtist; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs new file mode 100644 index 000000000..24e1f40da --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/AlbumComparer.cs @@ -0,0 +1,46 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class AlbumComparer + /// </summary> + public class AlbumComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); + } + + /// <summary> + /// Gets the value. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>System.String.</returns> + private string GetValue(BaseItem x) + { + var audio = x as Audio; + + return audio == null ? string.Empty : audio.Album; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.Album; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs b/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs new file mode 100644 index 000000000..278a39785 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/ArtistComparer.cs @@ -0,0 +1,46 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class ArtistComparer + /// </summary> + public class ArtistComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); + } + + /// <summary> + /// Gets the value. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>System.String.</returns> + private string GetValue(BaseItem x) + { + var audio = x as Audio; + + return audio == null ? string.Empty : audio.Artist; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.Artist; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs b/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs new file mode 100644 index 000000000..2e1b73ccf --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/CommunityRatingComparer.cs @@ -0,0 +1,29 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + public class CommunityRatingComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0); + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.CommunityRating; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs new file mode 100644 index 000000000..d340913c9 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -0,0 +1,33 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class DateCreatedComparer + /// </summary> + public class DateCreatedComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return DateTime.Compare(x.DateCreated, y.DateCreated); + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.DateCreated; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs new file mode 100644 index 000000000..49e464559 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -0,0 +1,56 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class DatePlayedComparer + /// </summary> + public class DatePlayedComparer : IUserBaseItemComparer + { + /// <summary> + /// Gets or sets the user. + /// </summary> + /// <value>The user.</value> + public User User { get; set; } + + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return GetDate(x).CompareTo(GetDate(y)); + } + + /// <summary> + /// Gets the date. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>DateTime.</returns> + private DateTime GetDate(BaseItem x) + { + var userdata = x.GetUserData(User, false); + + if (userdata != null && userdata.LastPlayedDate.HasValue) + { + return userdata.LastPlayedDate.Value; + } + + return DateTime.MaxValue; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.DatePlayed; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs new file mode 100644 index 000000000..2a8d52405 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -0,0 +1,52 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class PremiereDateComparer + /// </summary> + public class PremiereDateComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return GetDate(x).CompareTo(GetDate(y)); + } + + /// <summary> + /// Gets the date. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>DateTime.</returns> + private DateTime GetDate(BaseItem x) + { + if (x.PremiereDate.HasValue) + { + return x.PremiereDate.Value; + } + + if (x.ProductionYear.HasValue) + { + return new DateTime(x.ProductionYear.Value, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } + return DateTime.MaxValue; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.PremiereDate; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs b/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs new file mode 100644 index 000000000..47a03048c --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/ProductionYearComparer.cs @@ -0,0 +1,52 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class ProductionYearComparer + /// </summary> + public class ProductionYearComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return GetValue(x).CompareTo(GetValue(y)); + } + + /// <summary> + /// Gets the date. + /// </summary> + /// <param name="x">The x.</param> + /// <returns>DateTime.</returns> + private int GetValue(BaseItem x) + { + if (x.ProductionYear.HasValue) + { + return x.ProductionYear.Value; + } + + if (x.PremiereDate.HasValue) + { + return x.PremiereDate.Value.Year; + } + + return 0; + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.ProductionYear; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs b/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs new file mode 100644 index 000000000..e7e98a8a0 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/RandomComparer.cs @@ -0,0 +1,33 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; +using System; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class RandomComparer + /// </summary> + public class RandomComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return Guid.NewGuid().CompareTo(Guid.NewGuid()); + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.Random; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs new file mode 100644 index 000000000..71893ef31 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/RuntimeComparer.cs @@ -0,0 +1,32 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class RuntimeComparer + /// </summary> + public class RuntimeComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.Runtime; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs new file mode 100644 index 000000000..067f8c453 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs @@ -0,0 +1,33 @@ +using MediaBrowser.Controller.Entities; +using System; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + /// <summary> + /// Class SortNameComparer + /// </summary> + public class SortNameComparer : IBaseItemComparer + { + /// <summary> + /// Compares the specified x. + /// </summary> + /// <param name="x">The x.</param> + /// <param name="y">The y.</param> + /// <returns>System.Int32.</returns> + public int Compare(BaseItem x, BaseItem y) + { + return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); + } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + public string Name + { + get { return ItemSortBy.SortName; } + } + } +} diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index c822aae84..e156c465b 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -18,6 +18,7 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Updates; using MediaBrowser.Controller.Weather; using MediaBrowser.IsoMounter; @@ -242,7 +243,7 @@ namespace MediaBrowser.ServerApplication ServerManager.AddWebSocketListeners(GetExports<IWebSocketListener>(false)); ServerManager.Start(); - LibraryManager.AddParts(GetExports<IResolverIgnoreRule>(), GetExports<IVirtualFolderCreator>(), GetExports<IItemResolver>(), GetExports<IIntroProvider>()); + LibraryManager.AddParts(GetExports<IResolverIgnoreRule>(), GetExports<IVirtualFolderCreator>(), GetExports<IItemResolver>(), GetExports<IIntroProvider>(), GetExports<IBaseItemComparer>()); ProviderManager.AddMetadataProviders(GetExports<BaseMetadataProvider>().OrderBy(e => e.Priority).ToArray()); } diff --git a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs index d567a9fd8..26e0978a3 100644 --- a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs +++ b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -78,7 +79,8 @@ namespace MediaBrowser.ServerApplication Cursor = Cursors.Wait; await Task.Run(() => { - IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children.OrderBy(i => i.SortName) : _libraryManager.RootFolder.GetChildren(CurrentUser, sortBy: LocalizedStrings.Instance.GetString("NameDispPref")); + IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser); + children = OrderByName(children, CurrentUser); foreach (Folder folder in children) { @@ -86,9 +88,12 @@ namespace MediaBrowser.ServerApplication var currentFolder = folder; Task.Factory.StartNew(() => { - var prefs = ddlProfile.SelectedItem != null ? currentFolder.GetDisplayPrefs(ddlProfile.SelectedItem as User, false) ?? new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")} : new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")}; + var prefs = ddlProfile.SelectedItem != null ? currentFolder.GetDisplayPrefs(ddlProfile.SelectedItem as User, false) ?? new DisplayPreferences {SortBy = ItemSortBy.SortName} : new DisplayPreferences {SortBy = ItemSortBy.SortName}; var node = new TreeViewItem { Tag = currentFolder }; - AddChildren(node, currentFolder.GetChildren(CurrentUser, prefs.IndexBy, prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref")), CurrentUser); + + var subChildren = currentFolder.GetChildren(CurrentUser, prefs.IndexBy); + subChildren = OrderByName(subChildren, CurrentUser); + AddChildren(node, subChildren, CurrentUser); node.Header = currentFolder.Name + " (" + node.Items.Count + ")"; tvwLibrary.Items.Add(node); @@ -101,6 +106,28 @@ namespace MediaBrowser.ServerApplication } /// <summary> + /// Orders the name of the by. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="user">The user.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + private IEnumerable<BaseItem> OrderByName(IEnumerable<BaseItem> items, User user) + { + return OrderBy(items, user, ItemSortBy.SortName); + } + + /// <summary> + /// Orders the name of the by. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="user">The user.</param> + /// <returns>IEnumerable{BaseItem}.</returns> + private IEnumerable<BaseItem> OrderBy(IEnumerable<BaseItem> items, User user, string order) + { + return _libraryManager.Sort(items, user, new[] { order }, SortOrder.Ascending); + } + + /// <summary> /// Adds the children. /// </summary> /// <param name="parent">The parent.</param> @@ -115,7 +142,7 @@ namespace MediaBrowser.ServerApplication if (subFolder != null) { var prefs = subFolder.GetDisplayPrefs(user, false) ?? new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")}; - AddChildren(node, subFolder.GetChildren(user, sortBy: prefs.SortBy), user); + AddChildren(node, OrderBy(subFolder.GetChildren(user), user, prefs.SortBy), user); node.Header = item.Name + " (" + node.Items.Count + ")"; } else @@ -152,14 +179,29 @@ namespace MediaBrowser.ServerApplication { lblIndexBy.Visibility = ddlIndexBy.Visibility = ddlSortBy.Visibility = lblSortBy.Visibility = Visibility.Visible; ddlIndexBy.ItemsSource = folder.IndexByOptionStrings; - ddlSortBy.ItemsSource = folder.SortByOptionStrings; + + ddlSortBy.ItemsSource = new [] + { + ItemSortBy.SortName, + ItemSortBy.Album, + ItemSortBy.AlbumArtist, + ItemSortBy.Artist, + ItemSortBy.CommunityRating, + ItemSortBy.DateCreated, + ItemSortBy.DatePlayed, + ItemSortBy.PremiereDate, + ItemSortBy.ProductionYear, + ItemSortBy.Random, + ItemSortBy.Runtime + }; + var prefs = folder.GetDisplayPrefs(ddlProfile.SelectedItem as User, false); ddlIndexBy.SelectedItem = prefs != null ? prefs.IndexBy ?? LocalizedStrings.Instance.GetString("NoneDispPref") : LocalizedStrings.Instance.GetString("NoneDispPref"); ddlSortBy.SelectedItem = prefs != null - ? prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref") - : LocalizedStrings.Instance.GetString("NameDispPref"); + ? prefs.SortBy ?? ItemSortBy.SortName + : ItemSortBy.SortName; } else { @@ -311,7 +353,7 @@ namespace MediaBrowser.ServerApplication var folder = treeItem != null ? treeItem.Tag as Folder : null; - var prefs = folder != null ? folder.GetDisplayPrefs(CurrentUser, true) : new DisplayPreferences {SortBy = LocalizedStrings.Instance.GetString("NameDispPref")}; + var prefs = folder != null ? folder.GetDisplayPrefs(CurrentUser, true) : new DisplayPreferences {SortBy = ItemSortBy.SortName}; if (folder != null && prefs.IndexBy != ddlIndexBy.SelectedItem as string) { //grab UI context so we can update within the below task @@ -326,7 +368,7 @@ namespace MediaBrowser.ServerApplication //re-build the current item's children as an index prefs.IndexBy = ddlIndexBy.SelectedItem as string; treeItem.Items.Clear(); - AddChildren(treeItem,folder.GetChildren(CurrentUser, prefs.IndexBy, prefs.SortBy), CurrentUser); + AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser); treeItem.Header = folder.Name + "(" + treeItem.Items.Count + ")"; Cursor = Cursors.Arrow; @@ -367,7 +409,7 @@ namespace MediaBrowser.ServerApplication //re-sort prefs.SortBy = ddlSortBy.SelectedItem as string; treeItem.Items.Clear(); - AddChildren(treeItem,folder.GetChildren(CurrentUser,prefs.IndexBy, prefs.SortBy ?? LocalizedStrings.Instance.GetString("NameDispPref")), CurrentUser); + AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser); treeItem.Header = folder.Name + "(" + treeItem.Items.Count + ")"; Cursor = Cursors.Arrow; diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index ec3137d83..88ef97950 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -76,7 +76,7 @@ </ManifestKeyFile> </PropertyGroup> <PropertyGroup> - <GenerateManifests>true</GenerateManifests> + <GenerateManifests>false</GenerateManifests> </PropertyGroup> <PropertyGroup> <SignManifests>false</SignManifests> @@ -112,6 +112,9 @@ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> + <PropertyGroup> + <TargetZone>LocalIntranet</TargetZone> + </PropertyGroup> <ItemGroup> <Reference Include="Hardcodet.Wpf.TaskbarNotification"> <HintPath>..\packages\Hardcodet.Wpf.TaskbarNotification.1.0.4.0\lib\net40\Hardcodet.Wpf.TaskbarNotification.dll</HintPath> diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication_TemporaryKey.pfx b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication_TemporaryKey.pfx Binary files differdeleted file mode 100644 index 64676b054..000000000 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication_TemporaryKey.pfx +++ /dev/null |
