diff --git a/Resources/Raw/whats-new.html b/Resources/Raw/whats-new.html index 278c952..77b41ac 100644 --- a/Resources/Raw/whats-new.html +++ b/Resources/Raw/whats-new.html @@ -9,6 +9,14 @@ margin-top: 0!important; } +

Version 1.4.7 - January 6th, 2024

+

Happy new year!

+

Version 1.4.6 - December 26th, 2023

#38 Error logs will now be correctly exported when that feature is used, rather than an empty file.

Version 1.4.5 - December 3rd, 2023

diff --git a/RosyCrow.csproj b/RosyCrow.csproj index 08c5f53..2fd2f98 100644 --- a/RosyCrow.csproj +++ b/RosyCrow.csproj @@ -92,14 +92,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Services/Cache/DiskCacheService.cs b/Services/Cache/DiskCacheService.cs index ac8351d..a839b7e 100644 --- a/Services/Cache/DiskCacheService.cs +++ b/Services/Cache/DiskCacheService.cs @@ -26,11 +26,11 @@ public DiskCacheService(ILogger logger) _logger.LogInformation(@"{Count} cache buckets pruned upon initialization", prunedCount); } - public async Task TryRead(Uri uri, Stream destination) + public async Task TryRead(Uri uri, Stream destination, bool isImage) { try { - if (!TryFindCachedByUri(uri, out var path)) + if (!TryFindCachedByUri(uri, isImage, out var path)) return false; _logger.LogDebug(@"Cached resource found at {Path}", path); @@ -52,11 +52,11 @@ public async Task TryRead(Uri uri, Stream destination) } } - public async Task Write(Uri uri, Stream contents) + public async Task Write(Uri uri, Stream contents, bool isImage) { try { - var path = GetCurrentPathFromUri(uri); + var path = GetCurrentPathFromUri(uri, isImage); _logger.LogDebug(@"Cached page file path is {Path}", path); @@ -114,15 +114,15 @@ private static string GetRootPath() return FileSystem.CacheDirectory; } - private bool TryFindCachedByUri(Uri uri, out string path) + private bool TryFindCachedByUri(Uri uri, bool isImage, out string path) { // happy path: resource exists in the current hourly bucket - path = GetCurrentPathFromUri(uri); + path = GetCurrentPathFromUri(uri, isImage); if (File.Exists(path)) return true; - var key = ComputeUriCachePath(uri); + var key = ComputeUriCachePath(uri, isImage); foreach (var bucket in Directory.GetDirectories(GetRootPath())) { path = Path.Combine(bucket, key); @@ -130,7 +130,7 @@ private bool TryFindCachedByUri(Uri uri, out string path) if (File.Exists(path)) { // move this file into the current bucket so we find it more quickly next time - var newPath = GetCurrentPathFromUri(uri); + var newPath = GetCurrentPathFromUri(uri, isImage); var directory = Path.GetDirectoryName(newPath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) @@ -151,9 +151,9 @@ private bool TryFindCachedByUri(Uri uri, out string path) return false; } - private static string GetCurrentPathFromUri(Uri uri) + private static string GetCurrentPathFromUri(Uri uri, bool isImage) { - return Path.Combine(GetRootPath(), GetHourlyDirectoryName(), ComputeUriCachePath(uri)); + return Path.Combine(GetRootPath(), GetHourlyDirectoryName(), ComputeUriCachePath(uri, isImage)); } private static string ComputeCachePath(string bucket, string key) @@ -163,9 +163,10 @@ private static string ComputeCachePath(string bucket, string key) Convert.ToHexString(MD5.HashData(Encoding.Default.GetBytes(key)))[..12] + ".dat"); } - private static string ComputeUriCachePath(Uri uri) + private static string ComputeUriCachePath(Uri uri, bool isImage) { - return ComputeCachePath(uri.Host.ToUpperInvariant(), uri.PathAndQuery); + var path = ComputeCachePath(uri.Host.ToUpperInvariant(), uri.PathAndQuery); + return isImage ? Path.Combine("images/", path) : path; } private static string GetHourlyDirectoryName() diff --git a/Services/Cache/ICacheService.cs b/Services/Cache/ICacheService.cs index b597e6a..3349064 100644 --- a/Services/Cache/ICacheService.cs +++ b/Services/Cache/ICacheService.cs @@ -2,6 +2,6 @@ public interface ICacheService { - Task TryRead(Uri uri, Stream destination); - Task Write(Uri uri, Stream contents); + Task TryRead(Uri uri, Stream destination, bool isImage); + Task Write(Uri uri, Stream contents, bool isImage); } \ No newline at end of file diff --git a/Services/Document/DocumentService.cs b/Services/Document/DocumentService.cs index 8957d91..6b805e7 100644 --- a/Services/Document/DocumentService.cs +++ b/Services/Document/DocumentService.cs @@ -158,7 +158,7 @@ public async Task RenderGemtextAsHtml(GemtextResponse g // cache the page prior to injecting the stylesheet await using var pageBuffer = new MemoryStream(Encoding.UTF8.GetBytes(document.DocumentNode.OuterHtml)); - await _cache.Write(gemtext.Uri, pageBuffer); + await _cache.Write(gemtext.Uri, pageBuffer, false); return new RenderedGemtextDocument { HtmlContents = document.DocumentNode.OuterHtml, Title = title }; @@ -246,7 +246,7 @@ private static async Task CreateInlinedImagePreview(Stream source, using var downsized = image.Downsize(256.0f, true); var output = new MemoryStream(); - await downsized.SaveAsync(output); + await downsized.SaveAsync(output, ImageFormat.Jpeg, 0.75f); return output; } @@ -263,7 +263,7 @@ private async Task TryLoadCachedImage(Uri uri) { var image = new MemoryStream(); - if (await _cache.TryRead(uri, image)) + if (await _cache.TryRead(uri, image, true)) { _logger.LogDebug(@"Loaded cached image originally from {URI}", uri); return CreateInlineImageDataUrl(image); @@ -308,7 +308,7 @@ private async Task FetchAndCacheInlinedImage(Uri uri) } image.Seek(0, SeekOrigin.Begin); - await _cache.Write(uri, image); + await _cache.Write(uri, image, true); _logger.LogDebug(@"Loaded an inlined image from {URI} after {Attempt} attempt(s)", uri, i + 1); diff --git a/Services/Identity/IdentityService.cs b/Services/Identity/IdentityService.cs index fdd1bd1..62b1f63 100644 --- a/Services/Identity/IdentityService.cs +++ b/Services/Identity/IdentityService.cs @@ -131,7 +131,7 @@ public async Task Activate(Models.Identity identity) return; // the identity has already been loaded - if (ActiveCertificate != null) + if (ActiveCertificate?.Thumbprint == identity.Hash) return; _unlockingIdentity = true; diff --git a/Views/BrowserView.xaml.cs b/Views/BrowserView.xaml.cs index 4a9f4b9..5ce3625 100644 --- a/Views/BrowserView.xaml.cs +++ b/Views/BrowserView.xaml.cs @@ -322,7 +322,7 @@ public async Task LoadPage(bool triggeredByRefresh = false, bool useCache = fals { var cached = new MemoryStream(); - if (await _cache.TryRead(_tab.Location, cached)) + if (await _cache.TryRead(_tab.Location, cached, false)) { _logger.LogInformation(@"Loading a cached copy of the page"); @@ -336,7 +336,7 @@ public async Task LoadPage(bool triggeredByRefresh = false, bool useCache = fals } } - if (!string.IsNullOrWhiteSpace(_tab.Input)) + if (_tab.Input != null) { _logger.LogInformation(@"User provided input ""{Input}""", _tab.Input); _tab.Location = new UriBuilder(_tab.Location) { Query = _tab.Input }.Uri; @@ -381,8 +381,8 @@ private async Task HandleTitanResponse(IGeminiResponse response, _tab.Input = await _tab.ParentPage.DisplayPromptOnMainThread(Text.BrowserView_LoadPage_Input_Required, inputRequired.Message); - if (string.IsNullOrEmpty(_tab.Input)) - return ResponseAction.Finished; // if no user-input was provided, then we cannot continue + if (_tab.Input == null) + return ResponseAction.Finished; // if no user-input was provided, then we cannot continue (empty string is valid) return ResponseAction.Retry; } @@ -431,12 +431,11 @@ private async Task HandleGeminiResponse(IGeminiResponse response _tab.Input = await _tab.ParentPage.DisplayPromptOnMainThread(Text.BrowserView_LoadPage_Input_Required, inputRequired.Message); - ; - if (string.IsNullOrEmpty(_tab.Input)) + if (_tab.Input == null) { _settingsDatabase.LastVisitedUrl = response.Uri.ToString(); - return ResponseAction.Finished; // if no user-input was provided, then we cannot continue + return ResponseAction.Finished; // if no user-input was provided, then we cannot continue (empty string is valid) } return ResponseAction.Retry;