|  | @@ -1,4 +1,5 @@
 | 
	
		
			
				|  |  | -using MediaBrowser.Common.Extensions;
 | 
	
		
			
				|  |  | +using System.Globalization;
 | 
	
		
			
				|  |  | +using MediaBrowser.Common.Extensions;
 | 
	
		
			
				|  |  |  using MediaBrowser.Common.IO;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Channels;
 | 
	
		
			
				|  |  |  using MediaBrowser.Controller.Configuration;
 | 
	
	
		
			
				|  | @@ -299,8 +300,25 @@ namespace MediaBrowser.Server.Implementations.Channels
 | 
	
		
			
				|  |  |                  ? null
 | 
	
		
			
				|  |  |                  : _userManager.GetUserById(new Guid(query.UserId));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var itemsResult = await GetChannelItems(channelProvider, user, query.FolderId, providerStartIndex, providerLimit, cancellationToken)
 | 
	
		
			
				|  |  | -                        .ConfigureAwait(false);
 | 
	
		
			
				|  |  | +            ChannelItemSortField? sortField = null;
 | 
	
		
			
				|  |  | +            ChannelItemSortField parsedField;
 | 
	
		
			
				|  |  | +            if (query.SortBy.Length == 1 && 
 | 
	
		
			
				|  |  | +                Enum.TryParse(query.SortBy[0], true, out parsedField))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                sortField = parsedField;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var sortDescending = query.SortOrder.HasValue && query.SortOrder.Value == SortOrder.Descending;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var itemsResult = await GetChannelItems(channelProvider, 
 | 
	
		
			
				|  |  | +                user, 
 | 
	
		
			
				|  |  | +                query.FolderId, 
 | 
	
		
			
				|  |  | +                providerStartIndex, 
 | 
	
		
			
				|  |  | +                providerLimit, 
 | 
	
		
			
				|  |  | +                sortField,
 | 
	
		
			
				|  |  | +                sortDescending,
 | 
	
		
			
				|  |  | +                cancellationToken)
 | 
	
		
			
				|  |  | +                .ConfigureAwait(false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var providerTotalRecordCount = providerLimit.HasValue ? itemsResult.TotalRecordCount : null;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -322,9 +340,16 @@ namespace MediaBrowser.Server.Implementations.Channels
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
 | 
	
		
			
				|  |  | -        private async Task<ChannelItemResult> GetChannelItems(IChannel channel, User user, string folderId, int? startIndex, int? limit, CancellationToken cancellationToken)
 | 
	
		
			
				|  |  | +        private async Task<ChannelItemResult> GetChannelItems(IChannel channel,
 | 
	
		
			
				|  |  | +            User user,
 | 
	
		
			
				|  |  | +            string folderId,
 | 
	
		
			
				|  |  | +            int? startIndex,
 | 
	
		
			
				|  |  | +            int? limit,
 | 
	
		
			
				|  |  | +            ChannelItemSortField? sortField,
 | 
	
		
			
				|  |  | +            bool sortDescending,
 | 
	
		
			
				|  |  | +            CancellationToken cancellationToken)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var cachePath = GetChannelDataCachePath(channel, user, folderId);
 | 
	
		
			
				|  |  | +            var cachePath = GetChannelDataCachePath(channel, user, folderId, sortField, sortDescending);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              try
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -376,7 +401,9 @@ namespace MediaBrowser.Server.Implementations.Channels
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      User = user,
 | 
	
		
			
				|  |  |                      StartIndex = startIndex,
 | 
	
		
			
				|  |  | -                    Limit = limit
 | 
	
		
			
				|  |  | +                    Limit = limit,
 | 
	
		
			
				|  |  | +                    SortBy = sortField,
 | 
	
		
			
				|  |  | +                    SortDescending = sortDescending
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (!string.IsNullOrWhiteSpace(folderId))
 | 
	
	
		
			
				|  | @@ -415,7 +442,11 @@ namespace MediaBrowser.Server.Implementations.Channels
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private string GetChannelDataCachePath(IChannel channel, User user, string folderId)
 | 
	
		
			
				|  |  | +        private string GetChannelDataCachePath(IChannel channel,
 | 
	
		
			
				|  |  | +            User user,
 | 
	
		
			
				|  |  | +            string folderId,
 | 
	
		
			
				|  |  | +            ChannelItemSortField? sortField,
 | 
	
		
			
				|  |  | +            bool sortDescending)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              var channelId = GetInternalChannelId(channel.Name).ToString("N");
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -423,7 +454,26 @@ namespace MediaBrowser.Server.Implementations.Channels
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var version = string.IsNullOrWhiteSpace(channel.DataVersion) ? "0" : channel.DataVersion;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return Path.Combine(_config.ApplicationPaths.CachePath, "channels", channelId, version, folderKey, user.Id.ToString("N") + ".json");
 | 
	
		
			
				|  |  | +            var filename = user.Id.ToString("N");
 | 
	
		
			
				|  |  | +            var hashfilename = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (sortField.HasValue)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                filename += "-sortField-" + sortField.Value;
 | 
	
		
			
				|  |  | +                hashfilename = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (sortDescending)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                filename += "-sortDescending";
 | 
	
		
			
				|  |  | +                hashfilename = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (hashfilename)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                filename = filename.GetMD5().ToString("N");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return Path.Combine(_config.ApplicationPaths.CachePath, "channels", channelId, version, folderKey, filename + ".json");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<BaseItem> items, int? totalCountFromProvider, User user, ChannelItemQuery query, CancellationToken cancellationToken)
 |