diff --git a/src/Markdowser/Utilities/CacheService.cs b/src/Markdowser/Utilities/CacheService.cs index 2cff353..2ed4999 100644 --- a/src/Markdowser/Utilities/CacheService.cs +++ b/src/Markdowser/Utilities/CacheService.cs @@ -1,15 +1,13 @@ using Markdowser.ViewModels; using System.Collections.Generic; -namespace Markdowser.Utilities -{ namespace Markdowser.Utilities { public class CacheService { private Dictionary cache = new Dictionary(); - public ContentViewModelBase Get(string url) + public ContentViewModelBase? Get(string url) { if (cache.ContainsKey(url)) { @@ -26,5 +24,4 @@ namespace Markdowser.Utilities cache[url] = content; } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/Markdowser/ViewModels/MainWindowViewModel.cs b/src/Markdowser/ViewModels/MainWindowViewModel.cs index 3d68d7c..dc37d03 100644 --- a/src/Markdowser/ViewModels/MainWindowViewModel.cs +++ b/src/Markdowser/ViewModels/MainWindowViewModel.cs @@ -6,7 +6,6 @@ using Markdowser.Models; using Markdowser.Processing; using Markdowser.Processing.Processors; using Markdowser.Utilities; -using Markdowser.Utilities.Markdowser.Utilities; using Markdowser.ViewModels.Content; using ReactiveUI; @@ -103,6 +102,8 @@ public partial class MainWindowViewModel : ViewModelBase public bool ForwardEnabled => GlobalState.ForwardHistory.Count > 0; public bool ProgressIndeterminate => Progress == 0; public ICommand Browse => ReactiveCommand.Create(FetchUrl); + public ICommand Reload => ReactiveCommand.Create(FetchUrlIgnoringCache); + public ICommand Back => ReactiveCommand.Create(() => { @@ -315,4 +316,93 @@ private void FetchUrl() } }); } + +private void FetchUrlIgnoringCache() +{ + if (IsBusy) + { + WindowNotificationManager.Show(new Notification("Busy", "The browser is currently busy.", NotificationType.Warning)); + return; + } + + if (string.IsNullOrWhiteSpace(Url)) + { + Content = DefaultContent; + Debug.WriteLine("URL is empty."); + CurrentTab.Header = "New Tab"; + return; + } + + if (!IsValidHttpUri(Url, out _)) + { + if (Url.StartsWith("//")) + { + Url = $"https:{Url}"; + } + else + { + // Search with duckduckgo + try + { + Url = string.Format(Settings.Current.SearchEngineUrl, Uri.EscapeDataString(Url)); + } + catch (FormatException ex) + { + WindowNotificationManager.Show(new Notification("Invalid Search Engine URL", $"{ex.Message}", NotificationType.Error)); + } + } + } + + IsBusy = true; + Progress = 0; + + _ = Task.Run(async () => + { + Debug.WriteLine("Fetching URL..."); + + try + { + HttpResponseMessage httpResponseMessage = await httpClient.GetAsync(Url); + + string? newUrl = httpResponseMessage.RequestMessage?.RequestUri?.ToString(); + + if (newUrl is not null && newUrl != Url) + { + string oldUrl = Url; + Dispatcher.UIThread.Post(() => WindowNotificationManager.Show(new Notification("Redirected", $"Redirected from\n{oldUrl}\nto\n{newUrl}", NotificationType.Warning))); + Url = newUrl; + } + + if (!httpResponseMessage.IsSuccessStatusCode) + { + IsBusy = false; + + StringBuilder errorMessage = new(); + + _ = errorMessage.AppendLine($"# {(int)httpResponseMessage.StatusCode} {httpResponseMessage.StatusCode}"); + _ = errorMessage.AppendLine($"Failed to fetch URL: {httpResponseMessage.ReasonPhrase}"); + + Content = new MarkdownContentViewModel("Error", errorMessage.ToString()); + return; + } + + Content = await contentProcessorManager.ProcessContent(httpResponseMessage, new Progress(p => Progress = p.Percentage)); + cacheService.Set(Url, Content); + + Dispatcher.UIThread.Post(() => CurrentTab.Header = Content.Title); + } + catch (HttpRequestException e) + { + // Handle exception + } + catch (Exception e) + { + // Handle exception + } + finally + { + IsBusy = false; + } + }); +} } \ No newline at end of file diff --git a/src/Markdowser/Views/MainWindow.axaml b/src/Markdowser/Views/MainWindow.axaml index e634897..b7edad5 100644 --- a/src/Markdowser/Views/MainWindow.axaml +++ b/src/Markdowser/Views/MainWindow.axaml @@ -32,7 +32,7 @@ - + @@ -85,6 +85,7 @@