From f90211b0d3a4531806bfe94d6e522dc39821b4c5 Mon Sep 17 00:00:00 2001 From: ta264 Date: Tue, 29 Sep 2020 21:46:04 +0100 Subject: [PATCH] Fixed: UI hanging after scrolling movie list too fast [common] --- src/Radarr.Http/ByteArrayResponse.cs | 21 +++++++++++++++++++ .../Frontend/Mappers/HtmlMapperBase.cs | 18 +++++++--------- .../Mappers/IMapHttpRequestsToDisk.cs | 5 +++-- .../Frontend/Mappers/MediaCoverProxyMapper.cs | 9 ++++---- .../Mappers/StaticResourceMapperBase.cs | 21 +++++++++++++------ .../Frontend/StaticResourceModule.cs | 9 ++++---- 6 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 src/Radarr.Http/ByteArrayResponse.cs diff --git a/src/Radarr.Http/ByteArrayResponse.cs b/src/Radarr.Http/ByteArrayResponse.cs new file mode 100644 index 000000000..eff06229c --- /dev/null +++ b/src/Radarr.Http/ByteArrayResponse.cs @@ -0,0 +1,21 @@ +using System.IO; +using Nancy; + +namespace Radarr.Http +{ + public class ByteArrayResponse : Response + { + public ByteArrayResponse(byte[] body, string contentType) + { + ContentType = contentType; + + Contents = stream => + { + using (var writer = new BinaryWriter(stream)) + { + writer.Write(body); + } + }; + } + } +} diff --git a/src/Radarr.Http/Frontend/Mappers/HtmlMapperBase.cs b/src/Radarr.Http/Frontend/Mappers/HtmlMapperBase.cs index 4c5252303..d9becf153 100644 --- a/src/Radarr.Http/Frontend/Mappers/HtmlMapperBase.cs +++ b/src/Radarr.Http/Frontend/Mappers/HtmlMapperBase.cs @@ -1,6 +1,7 @@ using System; -using System.IO; +using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; using Nancy; using NLog; using NzbDrone.Common.Disk; @@ -28,21 +29,16 @@ protected HtmlMapperBase(IDiskProvider diskProvider, protected string HtmlPath; protected string UrlBase; - protected override Stream GetContentStream(string filePath) + protected override Task GetContent(string filePath) { var text = GetHtmlText(); - - var stream = new MemoryStream(); - var writer = new StreamWriter(stream); - writer.Write(text); - writer.Flush(); - stream.Position = 0; - return stream; + var data = Encoding.UTF8.GetBytes(text); + return Task.FromResult(data); } - public override Response GetResponse(string resourceUrl) + public async override Task GetResponse(string resourceUrl) { - var response = base.GetResponse(resourceUrl); + var response = await base.GetResponse(resourceUrl); response.Headers["X-UA-Compatible"] = "IE=edge"; return response; diff --git a/src/Radarr.Http/Frontend/Mappers/IMapHttpRequestsToDisk.cs b/src/Radarr.Http/Frontend/Mappers/IMapHttpRequestsToDisk.cs index 0bdc8c600..a0780e5b1 100644 --- a/src/Radarr.Http/Frontend/Mappers/IMapHttpRequestsToDisk.cs +++ b/src/Radarr.Http/Frontend/Mappers/IMapHttpRequestsToDisk.cs @@ -1,4 +1,5 @@ -using Nancy; +using System.Threading.Tasks; +using Nancy; namespace Radarr.Http.Frontend.Mappers { @@ -6,6 +7,6 @@ public interface IMapHttpRequestsToDisk { string Map(string resourceUrl); bool CanHandle(string resourceUrl); - Response GetResponse(string resourceUrl); + Task GetResponse(string resourceUrl); } } diff --git a/src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs b/src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs index 23e2876ca..111e9c5c8 100644 --- a/src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs +++ b/src/Radarr.Http/Frontend/Mappers/MediaCoverProxyMapper.cs @@ -1,8 +1,7 @@ using System; -using System.IO; using System.Text.RegularExpressions; +using System.Threading.Tasks; using Nancy; -using Nancy.Responses; using NzbDrone.Core.MediaCover; namespace Radarr.Http.Frontend.Mappers @@ -28,13 +27,13 @@ public bool CanHandle(string resourceUrl) return resourceUrl.StartsWith("/MediaCoverProxy/", StringComparison.InvariantCultureIgnoreCase); } - public Response GetResponse(string resourceUrl) + public Task GetResponse(string resourceUrl) { var match = _regex.Match(resourceUrl); if (!match.Success) { - return new NotFoundResponse(); + return Task.FromResult(new NotFoundResponse()); } var hash = match.Groups["hash"].Value; @@ -42,7 +41,7 @@ public Response GetResponse(string resourceUrl) var imageData = _mediaCoverProxy.GetImage(hash); - return new StreamResponse(() => new MemoryStream(imageData), MimeTypes.GetMimeType(filename)); + return Task.FromResult(new ByteArrayResponse(imageData, MimeTypes.GetMimeType(filename))); } } } diff --git a/src/Radarr.Http/Frontend/Mappers/StaticResourceMapperBase.cs b/src/Radarr.Http/Frontend/Mappers/StaticResourceMapperBase.cs index ee8a37c78..cef93719d 100644 --- a/src/Radarr.Http/Frontend/Mappers/StaticResourceMapperBase.cs +++ b/src/Radarr.Http/Frontend/Mappers/StaticResourceMapperBase.cs @@ -1,7 +1,7 @@ using System; using System.IO; +using System.Threading.Tasks; using Nancy; -using Nancy.Responses; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; @@ -28,14 +28,15 @@ protected StaticResourceMapperBase(IDiskProvider diskProvider, Logger logger) public abstract bool CanHandle(string resourceUrl); - public virtual Response GetResponse(string resourceUrl) + public async virtual Task GetResponse(string resourceUrl) { var filePath = Map(resourceUrl); if (_diskProvider.FileExists(filePath, _caseSensitive)) { - var response = new StreamResponse(() => GetContentStream(filePath), MimeTypes.GetMimeType(filePath)); - return new MaterialisingResponse(response); + var data = await GetContent(filePath).ConfigureAwait(false); + + return new ByteArrayResponse(data, MimeTypes.GetMimeType(filePath)); } _logger.Warn("File {0} not found", filePath); @@ -43,9 +44,17 @@ public virtual Response GetResponse(string resourceUrl) return NotFoundResponse; } - protected virtual Stream GetContentStream(string filePath) + protected async virtual Task GetContent(string filePath) { - return File.OpenRead(filePath); + using (var output = new MemoryStream()) + { + using (var file = File.OpenRead(filePath)) + { + await file.CopyToAsync(output).ConfigureAwait(false); + } + + return output.ToArray(); + } } } } diff --git a/src/Radarr.Http/Frontend/StaticResourceModule.cs b/src/Radarr.Http/Frontend/StaticResourceModule.cs index 83c162551..cb9d805d0 100644 --- a/src/Radarr.Http/Frontend/StaticResourceModule.cs +++ b/src/Radarr.Http/Frontend/StaticResourceModule.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Nancy; using NLog; using Radarr.Http.Frontend.Mappers; @@ -17,11 +18,11 @@ public StaticResourceModule(IEnumerable requestMappers, _requestMappers = requestMappers; _logger = logger; - Get("/{resource*}", x => Index()); - Get("/", x => Index()); + Get("/{resource*}", async (x, ct) => await Index()); + Get("/", async (x, ct) => await Index()); } - private Response Index() + private async Task Index() { var path = Request.Url.Path; @@ -37,7 +38,7 @@ private Response Index() if (mapper != null) { - return mapper.GetResponse(path); + return await mapper.GetResponse(path); } _logger.Warn("Couldn't find handler for {0}", path);