diff --git a/Jellyfin.Plugin.MetaTube/Extensions/EmbyExtensions.cs b/Jellyfin.Plugin.MetaTube/Extensions/EmbyExtensions.cs index d53ea62..7f63e1d 100644 --- a/Jellyfin.Plugin.MetaTube/Extensions/EmbyExtensions.cs +++ b/Jellyfin.Plugin.MetaTube/Extensions/EmbyExtensions.cs @@ -1,4 +1,6 @@ #if __EMBY__ + +using System.Text; using MediaBrowser.Model.Logging; namespace Jellyfin.Plugin.MetaTube.Extensions; @@ -13,6 +15,115 @@ public static class EmbyExtensions } #endregion + + #region Sorting + + public static IEnumerable OrderByString(this IEnumerable list, Func getName) + { + return list.OrderBy(getName, new AlphanumComparator()); + } + + public static IEnumerable OrderByStringDescending( + this IEnumerable list, + Func getName) + { + return list.OrderByDescending(getName, new AlphanumComparator()); + } + + public static IOrderedEnumerable ThenByString( + this IOrderedEnumerable list, + Func getName) + { + return list.ThenBy(getName, new AlphanumComparator()); + } + + public static IOrderedEnumerable ThenByStringDescending( + this IOrderedEnumerable list, + Func getName) + { + return list.ThenByDescending(getName, new AlphanumComparator()); + } + + private sealed class AlphanumComparator : IComparer + { + public int Compare(string x, string y) + { + return CompareValues(x, y); + } + + private static bool InChunk(char ch, char otherCh) + { + var chunkType = ChunkType.Alphanumeric; + if (char.IsDigit(otherCh)) + chunkType = ChunkType.Numeric; + return (chunkType != ChunkType.Alphanumeric || !char.IsDigit(ch)) && + (chunkType != ChunkType.Numeric || char.IsDigit(ch)); + } + + private static int CompareValues(string s1, string s2) + { + if (s1 == null || s2 == null) + return 0; + var index1 = 0; + var index2 = 0; + while (index1 < s1.Length || index2 < s2.Length) + { + if (index1 >= s1.Length) + return -1; + if (index2 >= s2.Length) + return 1; + var ch1 = s1[index1]; + var ch2 = s2[index2]; + var stringBuilder1 = new StringBuilder(); + var stringBuilder2 = new StringBuilder(); + while (index1 < s1.Length && (stringBuilder1.Length == 0 || InChunk(ch1, stringBuilder1[0]))) + { + stringBuilder1.Append(ch1); + ++index1; + if (index1 < s1.Length) + ch1 = s1[index1]; + } + + while (index2 < s2.Length && (stringBuilder2.Length == 0 || InChunk(ch2, stringBuilder2[0]))) + { + stringBuilder2.Append(ch2); + ++index2; + if (index2 < s2.Length) + ch2 = s2[index2]; + } + + var num = 0; + if (char.IsDigit(stringBuilder1[0]) && char.IsDigit(stringBuilder2[0])) + { + if (!int.TryParse(stringBuilder1.ToString(), out var result1) || + !int.TryParse(stringBuilder2.ToString(), out var result2)) + return 0; + if (result1 < result2) + num = -1; + if (result1 > result2) + num = 1; + } + else + { + num = string.Compare(stringBuilder1.ToString(), stringBuilder2.ToString(), + StringComparison.CurrentCulture); + } + + if (num != 0) + return num; + } + + return 0; + } + + private enum ChunkType + { + Alphanumeric, + Numeric + } + } + + #endregion } #endif \ No newline at end of file diff --git a/Jellyfin.Plugin.MetaTube/Jellyfin.Plugin.MetaTube.csproj b/Jellyfin.Plugin.MetaTube/Jellyfin.Plugin.MetaTube.csproj index 9d542dc..2b8eb54 100644 --- a/Jellyfin.Plugin.MetaTube/Jellyfin.Plugin.MetaTube.csproj +++ b/Jellyfin.Plugin.MetaTube/Jellyfin.Plugin.MetaTube.csproj @@ -25,39 +25,39 @@ - + - - + + - + - - + + - - + + - - - + + + - - - - - + + + + + diff --git a/Jellyfin.Plugin.MetaTube/ScheduledTasks/OrganizeMetadataTask.cs b/Jellyfin.Plugin.MetaTube/ScheduledTasks/OrganizeMetadataTask.cs index 1f21809..54dc109 100644 --- a/Jellyfin.Plugin.MetaTube/ScheduledTasks/OrganizeMetadataTask.cs +++ b/Jellyfin.Plugin.MetaTube/ScheduledTasks/OrganizeMetadataTask.cs @@ -2,7 +2,6 @@ using System.Text.RegularExpressions; using Jellyfin.Plugin.MetaTube.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Tasks; #if __EMBY__ @@ -10,6 +9,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Model.Logging; #else +using MediaBrowser.Controller.Sorting; using Microsoft.Extensions.Logging; using Jellyfin.Data.Enums; #endif