mirror of
https://github.com/Stone-Red-Code/Markdowser.git
synced 2026-09-04 09:06:15 +02:00
+140
@@ -396,3 +396,143 @@ FodyWeavers.xsd
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
# Azure Toolkit for IntelliJ plugin
|
||||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||
.idea/**/azureSettings.xml
|
||||
|
||||
### Rider ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
|
||||
# AWS User-specific
|
||||
|
||||
# Generated files
|
||||
|
||||
# Sensitive or high-churn files
|
||||
|
||||
# Gradle
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
Generated
+1
@@ -0,0 +1 @@
|
||||
Markdowser
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoGeneratedRunConfigurationManager">
|
||||
<projectFile>Markdowser/Markdowser.csproj</projectFile>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="35ad98ab-fce0-4c9e-9180-ec9795d8ed8e" name="Changes" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="DpaMonitoringSettings">
|
||||
<option name="autoShow" value="false" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 6
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="2fg8GifhQMdOrTygPnNJLDd0rxo" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
".NET Project.Markdowser.executor": "Run",
|
||||
"git-widget-placeholder": "develop",
|
||||
"node.js.selected.package.tslint": "(autodetect)"
|
||||
},
|
||||
"keyToStringList": {
|
||||
"rider.external.source.directories": [
|
||||
"C:\\Users\\Camer\\AppData\\Roaming\\JetBrains\\Rider2024.1\\resharper-host\\DecompilerCache",
|
||||
"C:\\Users\\Camer\\AppData\\Roaming\\JetBrains\\Rider2024.1\\resharper-host\\SourcesCache",
|
||||
"C:\\Users\\Camer\\AppData\\Local\\Symbols\\src"
|
||||
]
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager">
|
||||
<configuration name="Markdowser" type="DotNetProject" factoryName=".NET Project" temporary="true">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/Markdowser/bin/Debug/net8.0/Markdowser.exe" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Markdowser/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Markdowser/Markdowser.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue=".NET Project.Markdowser" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Markdowser.ViewModels;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Markdowser.Utilities;
|
||||
|
||||
public class CacheService
|
||||
{
|
||||
private readonly Dictionary<string, ContentViewModelBase> cache = [];
|
||||
|
||||
public ContentViewModelBase? Get(string url)
|
||||
{
|
||||
if (cache.TryGetValue(url, out ContentViewModelBase? value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(string url, ContentViewModelBase content)
|
||||
{
|
||||
cache[url] = content;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,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!;
|
||||
@@ -48,7 +49,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
Url = value?.Tag?.ToString() ?? string.Empty;
|
||||
|
||||
FetchUrl();
|
||||
FetchUrl(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +100,8 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
public bool BackEnabled => GlobalState.BackHistory.Count > 0;
|
||||
public bool ForwardEnabled => GlobalState.ForwardHistory.Count > 0;
|
||||
public bool ProgressIndeterminate => Progress == 0;
|
||||
public ICommand Browse => ReactiveCommand.Create(FetchUrl);
|
||||
public ICommand Browse => ReactiveCommand.Create(() => FetchUrl(true));
|
||||
public ICommand Reload => ReactiveCommand.Create(() => FetchUrl(false));
|
||||
|
||||
public ICommand Back => ReactiveCommand.Create(() =>
|
||||
{
|
||||
@@ -208,7 +210,7 @@ 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(bool useCache = true)
|
||||
{
|
||||
if (IsBusy)
|
||||
{
|
||||
@@ -260,32 +262,41 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
try
|
||||
{
|
||||
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync(Url);
|
||||
|
||||
string? newUrl = httpResponseMessage.RequestMessage?.RequestUri?.ToString();
|
||||
|
||||
if (newUrl is not null && newUrl != Url)
|
||||
ContentViewModelBase? cachedContent = cacheService.Get(Url);
|
||||
if (cachedContent is not null && useCache)
|
||||
{
|
||||
string oldUrl = Url;
|
||||
Dispatcher.UIThread.Post(() => WindowNotificationManager.Show(new Notification("Redirected", $"Redirected from\n{oldUrl}\nto\n{newUrl}", NotificationType.Warning)));
|
||||
Url = newUrl;
|
||||
Content = cachedContent;
|
||||
}
|
||||
|
||||
if (!httpResponseMessage.IsSuccessStatusCode)
|
||||
else
|
||||
{
|
||||
IsBusy = false;
|
||||
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync(Url);
|
||||
|
||||
StringBuilder errorMessage = new();
|
||||
string? newUrl = httpResponseMessage.RequestMessage?.RequestUri?.ToString();
|
||||
|
||||
_ = errorMessage.AppendLine($"# {(int)httpResponseMessage.StatusCode} {httpResponseMessage.StatusCode}");
|
||||
_ = errorMessage.AppendLine($"Failed to fetch URL: {httpResponseMessage.ReasonPhrase}");
|
||||
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;
|
||||
}
|
||||
|
||||
Content = new MarkdownContentViewModel("Error", errorMessage.ToString());
|
||||
return;
|
||||
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<ProcessingProgress>(p => Progress = p.Percentage));
|
||||
cacheService.Set(Url, Content);
|
||||
}
|
||||
|
||||
Content = await contentProcessorManager.ProcessContent(httpResponseMessage, new Progress<ProcessingProgress>(p => Progress = p.Percentage));
|
||||
|
||||
Dispatcher.UIThread.Post(() => CurrentTab.Header = Content.Title);
|
||||
|
||||
Logger.LogInfo($"Fetched URL: {Url}");
|
||||
|
||||
@@ -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">
|
||||
|
||||
<Grid>
|
||||
|
||||
@@ -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">
|
||||
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
</Window.Resources>
|
||||
|
||||
<Window.KeyBindings>
|
||||
<KeyBinding Gesture="Ctrl+R" Command="{Binding Browse}" />
|
||||
<KeyBinding Gesture="F5" Command="{Binding Browse}" />
|
||||
<KeyBinding Gesture="Ctrl+R" Command="{Binding Reload}" />
|
||||
<KeyBinding Gesture="F5" Command="{Binding Reload}" />
|
||||
<KeyBinding Gesture="Alt+Home" Command="{StaticResource HomeCommand}" />
|
||||
<KeyBinding Gesture="Alt+H" Command="{StaticResource HomeCommand}" />
|
||||
<KeyBinding Gesture="Alt+Left" Command="{Binding Back}" />
|
||||
@@ -104,7 +104,7 @@
|
||||
</MultiBinding>
|
||||
</Button.IsEnabled>
|
||||
</Button>
|
||||
<Button Grid.Column="2" i:Attached.Icon="fa-solid fa-rotate-right" Command="{Binding Browse}" IsEnabled="{Binding !IsBusy}" />
|
||||
<Button Grid.Column="2" i:Attached.Icon="fa-solid fa-rotate-right" Command="{Binding Reload}" IsEnabled="{Binding !IsBusy}" />
|
||||
<Button Grid.Column="3" i:Attached.Icon="fa-solid fa-house" Command="{StaticResource HomeCommand}" IsEnabled="{Binding !IsBusy}" />
|
||||
|
||||
<Grid Grid.Column="4">
|
||||
|
||||
Reference in New Issue
Block a user