diff --git a/src/.idea/.idea.Markdowser/.idea/.name b/src/.idea/.idea.Markdowser/.idea/.name
new file mode 100644
index 0000000..3442041
--- /dev/null
+++ b/src/.idea/.idea.Markdowser/.idea/.name
@@ -0,0 +1 @@
+Markdowser
\ No newline at end of file
diff --git a/src/.idea/.idea.Markdowser/.idea/indexLayout.xml b/src/.idea/.idea.Markdowser/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/src/.idea/.idea.Markdowser/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/.idea.Markdowser/.idea/projectSettingsUpdater.xml b/src/.idea/.idea.Markdowser/.idea/projectSettingsUpdater.xml
new file mode 100644
index 0000000..4bb9f4d
--- /dev/null
+++ b/src/.idea/.idea.Markdowser/.idea/projectSettingsUpdater.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/.idea.Markdowser/.idea/vcs.xml b/src/.idea/.idea.Markdowser/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/src/.idea/.idea.Markdowser/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.idea/.idea.Markdowser/.idea/workspace.xml b/src/.idea/.idea.Markdowser/.idea/workspace.xml
new file mode 100644
index 0000000..760e254
--- /dev/null
+++ b/src/.idea/.idea.Markdowser/.idea/workspace.xml
@@ -0,0 +1,80 @@
+
+
+
+ Markdowser/Markdowser.csproj
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Markdowser/Utilities/CacheService.cs b/src/Markdowser/Utilities/CacheService.cs
new file mode 100644
index 0000000..2cff353
--- /dev/null
+++ b/src/Markdowser/Utilities/CacheService.cs
@@ -0,0 +1,30 @@
+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)
+ {
+ if (cache.ContainsKey(url))
+ {
+ return cache[url];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public void Set(string url, ContentViewModelBase content)
+ {
+ cache[url] = content;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Markdowser/ViewModels/MainWindowViewModel.cs b/src/Markdowser/ViewModels/MainWindowViewModel.cs
index 44fcc0c..3d68d7c 100644
--- a/src/Markdowser/ViewModels/MainWindowViewModel.cs
+++ b/src/Markdowser/ViewModels/MainWindowViewModel.cs
@@ -6,6 +6,7 @@ using Markdowser.Models;
using Markdowser.Processing;
using Markdowser.Processing.Processors;
using Markdowser.Utilities;
+using Markdowser.Utilities.Markdowser.Utilities;
using Markdowser.ViewModels.Content;
using ReactiveUI;
@@ -26,6 +27,7 @@ public partial class MainWindowViewModel : ViewModelBase
{
private readonly HttpClient httpClient = new(new HttpClientHandler() { AllowAutoRedirect = true });
private readonly ContentProcessorManager contentProcessorManager = new();
+ private readonly CacheService cacheService = new CacheService();
private ContentViewModelBase content;
private TabItem currentTab = null!;
@@ -196,50 +198,57 @@ public partial class MainWindowViewModel : ViewModelBase
return Uri.TryCreate(uriString, UriKind.Absolute, out uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps);
}
- private void FetchUrl()
+private void FetchUrl()
+{
+ if (IsBusy)
{
- if (IsBusy)
- {
- WindowNotificationManager.Show(new Notification("Busy", "The browser is currently busy.", NotificationType.Warning));
- return;
- }
+ 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 (string.IsNullOrWhiteSpace(Url))
+ {
+ Content = DefaultContent;
+ Debug.WriteLine("URL is empty.");
+ CurrentTab.Header = "New Tab";
+ return;
+ }
- if (!IsValidHttpUri(Url, out _))
+ if (!IsValidHttpUri(Url, out _))
+ {
+ if (Url.StartsWith("//"))
{
- if (Url.StartsWith("//"))
+ Url = $"https:{Url}";
+ }
+ else
+ {
+ // Search with duckduckgo
+ try
{
- Url = $"https:{Url}";
+ 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
+ {
+ ContentViewModelBase cachedContent = cacheService.Get(Url);
+ if (cachedContent != null)
+ {
+ Content = cachedContent;
}
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);
@@ -266,42 +275,44 @@ public partial class MainWindowViewModel : ViewModelBase
}
Content = await contentProcessorManager.ProcessContent(httpResponseMessage, new Progress(p => Progress = p.Percentage));
-
- Dispatcher.UIThread.Post(() => CurrentTab.Header = Content.Title);
+ cacheService.Set(Url, Content);
}
- catch (HttpRequestException e)
+
+ Dispatcher.UIThread.Post(() => CurrentTab.Header = Content.Title);
+ }
+ catch (HttpRequestException e)
+ {
+ StringBuilder errorMessage = new();
+
+ if (e.StatusCode is not null)
{
- StringBuilder errorMessage = new();
-
- if (e.StatusCode is not null)
- {
- _ = errorMessage.AppendLine($"# {(int)e.StatusCode} {e.StatusCode}");
- Dispatcher.UIThread.Post(() => CurrentTab.Header = $"Error: {(int)e.StatusCode} {e.StatusCode}");
- }
- else
- {
- Dispatcher.UIThread.Post(() => CurrentTab.Header = $"Error: {e.GetType().Name}");
- }
-
- _ = errorMessage.AppendLine($"# {e.HttpRequestError}");
- _ = errorMessage.AppendLine($"Failed to fetch URL: {e.Message}");
-
- Content = new MarkdownContentViewModel("Error", errorMessage.ToString());
+ _ = errorMessage.AppendLine($"# {(int)e.StatusCode} {e.StatusCode}");
+ Dispatcher.UIThread.Post(() => CurrentTab.Header = $"Error: {(int)e.StatusCode} {e.StatusCode}");
}
- catch (Exception e)
+ else
{
- StringBuilder errorMessage = new();
-
- _ = errorMessage.AppendLine($"# {e.GetType().Name}");
- _ = errorMessage.AppendLine($"Failed to fetch URL: {e.Message}");
-
- Content = new MarkdownContentViewModel("Error", errorMessage.ToString());
Dispatcher.UIThread.Post(() => CurrentTab.Header = $"Error: {e.GetType().Name}");
}
- finally
- {
- IsBusy = false;
- }
- });
- }
+
+ _ = errorMessage.AppendLine($"# {e.HttpRequestError}");
+ _ = errorMessage.AppendLine($"Failed to fetch URL: {e.Message}");
+
+ Content = new MarkdownContentViewModel("Error", errorMessage.ToString());
+ }
+ catch (Exception e)
+ {
+ StringBuilder errorMessage = new();
+
+ _ = errorMessage.AppendLine($"# {e.GetType().Name}");
+ _ = errorMessage.AppendLine($"Failed to fetch URL: {e.Message}");
+
+ Content = new MarkdownContentViewModel("Error", errorMessage.ToString());
+ Dispatcher.UIThread.Post(() => CurrentTab.Header = $"Error: {e.GetType().Name}");
+ }
+ finally
+ {
+ IsBusy = false;
+ }
+ });
+}
}
\ No newline at end of file
diff --git a/src/Markdowser/Views/Content/CommonImageContentView.axaml b/src/Markdowser/Views/Content/CommonImageContentView.axaml
index 1426a1d..34c13f8 100644
--- a/src/Markdowser/Views/Content/CommonImageContentView.axaml
+++ b/src/Markdowser/Views/Content/CommonImageContentView.axaml
@@ -8,7 +8,8 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:md="https://github.com/whistyun/Markdown.Avalonia"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
- x:DataType="vm:Content.CommonImageContentViewModel"
+ xmlns:content="clr-namespace:Markdowser.ViewModels.Content"
+ x:DataType="content:CommonImageContentViewModel"
x:Class="Markdowser.Views.Content.CommonImageContentView">
diff --git a/src/Markdowser/Views/Content/MarkdownContentView.axaml b/src/Markdowser/Views/Content/MarkdownContentView.axaml
index 7ff5259..2627761 100644
--- a/src/Markdowser/Views/Content/MarkdownContentView.axaml
+++ b/src/Markdowser/Views/Content/MarkdownContentView.axaml
@@ -8,7 +8,8 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:md="https://github.com/whistyun/Markdown.Avalonia"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
- x:DataType="vm:Content.MarkdownContentViewModel"
+ xmlns:content="clr-namespace:Markdowser.ViewModels.Content"
+ x:DataType="content:MarkdownContentViewModel"
x:Class="Markdowser.Views.Content.MarkdownContentView">