1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Merge pull request #780 from Artemis-RGB/feature/plugin-help

Plugins - Added help pages
This commit is contained in:
RobertBeekman 2023-04-14 14:51:52 +02:00 committed by GitHub
commit 1bad68dbc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 175 additions and 98 deletions

View File

@ -44,31 +44,9 @@ public class ArtemisPluginException : Exception
public ArtemisPluginException(string message, Exception inner) : base(message, inner)
{
}
/// <summary>
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
/// </summary>
public ArtemisPluginException(string message, string helpDocument) : base(message)
{
HelpDocument = helpDocument;
}
/// <summary>
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
/// </summary>
public ArtemisPluginException(string message, Exception inner, string helpDocument) : base(message, inner)
{
HelpDocument = helpDocument;
}
/// <summary>
/// Gets the plugin the error is related to
/// </summary>
public Plugin? Plugin { get; }
/// <summary>
/// Gets or sets the help document related to this exception.
/// </summary>
public string? HelpDocument { get; }
}

View File

@ -57,7 +57,7 @@ public class Plugin : CorePropertyChanged, IDisposable
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
/// </summary>
public IPluginConfigurationDialog? ConfigurationDialog { get; set; }
/// <summary>
/// Indicates whether the user enabled the plugin or not
/// </summary>

View File

@ -27,6 +27,7 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
private bool _requiresAdmin;
private string _version = null!;
private Uri? _website;
private Uri? _helpPage;
internal PluginInfo()
{
@ -91,6 +92,16 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
get => _repository;
set => SetAndNotify(ref _repository, value);
}
/// <summary>
/// Gets or sets the help page of this plugin
/// </summary>
[JsonProperty]
public Uri? HelpPage
{
get => _helpPage;
set => SetAndNotify(ref _helpPage, value);
}
/// <summary>
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for

View File

@ -52,5 +52,17 @@
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Plugins\Features\PluginFeatureView.axaml.cs">
<DependentUpon>PluginFeatureView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteActionView.axaml.cs">
<DependentUpon>PluginPrerequisiteActionView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteView.axaml.cs">
<DependentUpon>PluginPrerequisiteView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@ -7,6 +7,8 @@ using Artemis.Core.LayerEffects;
using Artemis.Core.ScriptingProviders;
using Artemis.UI.Screens.Device;
using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.Plugins.Features;
using Artemis.UI.Screens.Plugins.Prerequisites;
using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
using Artemis.UI.Screens.ProfileEditor.ProfileTree;

View File

@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesInstallDialogView"
x:DataType="plugins:PluginPrerequisitesInstallDialogViewModel">
@ -34,7 +35,7 @@
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
IsHitTestVisible="False">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type plugins:PluginPrerequisiteViewModel}">
<DataTemplate DataType="{x:Type prerequisites:PluginPrerequisiteViewModel}">
<Grid ColumnDefinitions="Auto,*" Margin="0 6">
<Border Grid.Row="0" Grid.Column="0" Classes="status-border" IsVisible="{CompiledBinding !IsMet}" Background="#ff3838">
<avalonia:MaterialIcon Kind="Close" />

View File

@ -8,6 +8,7 @@ using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Screens.Plugins.Prerequisites;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Avalonia.Threading;

View File

@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesUninstallDialogView"
x:DataType="plugins:PluginPrerequisitesUninstallDialogViewModel">
@ -34,7 +35,7 @@
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
IsHitTestVisible="False">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type plugins:PluginPrerequisiteViewModel}">
<DataTemplate DataType="{x:Type prerequisites:PluginPrerequisiteViewModel}">
<StackPanel Margin="0 6" VerticalAlignment="Stretch">
<TextBlock FontWeight="Bold" Text="{CompiledBinding PluginPrerequisite.Name}" TextWrapping="Wrap" />
<TextBlock Text="{CompiledBinding PluginPrerequisite.Description}" TextWrapping="Wrap" />

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Screens.Plugins.Prerequisites;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Avalonia.Threading;

View File

@ -5,9 +5,10 @@
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
xmlns:features="clr-namespace:Artemis.UI.Screens.Plugins.Features"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginFeatureView"
x:DataType="plugins:PluginFeatureViewModel">
x:Class="Artemis.UI.Screens.Plugins.Features.PluginFeatureView"
x:DataType="features:PluginFeatureViewModel">
<Grid ColumnDefinitions="30,*,Auto">
<Grid.ContextFlyout>
<MenuFlyout>

View File

@ -1,7 +1,6 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Features;
public partial class PluginFeatureView : ReactiveUserControl<PluginFeatureViewModel>
{

View File

@ -18,12 +18,11 @@ using Avalonia.Threading;
using Material.Icons;
using ReactiveUI;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Features;
public class PluginFeatureViewModel : ActivatableViewModelBase
{
private readonly ICoreService _coreService;
private readonly INotificationService _notificationService;
private readonly IPluginManagementService _pluginManagementService;
private readonly IWindowService _windowService;
private bool _enabling;
@ -32,12 +31,10 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
bool showShield,
ICoreService coreService,
IWindowService windowService,
INotificationService notificationService,
IPluginManagementService pluginManagementService)
{
_coreService = coreService;
_windowService = windowService;
_notificationService = notificationService;
_pluginManagementService = pluginManagementService;
FeatureInfo = pluginFeatureInfo;
@ -176,11 +173,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
if (FeatureInfo.Instance == null)
{
this.RaisePropertyChanged(nameof(IsEnabled));
_notificationService.CreateNotification()
.WithMessage($"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.")
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.WithSeverity(NotificationSeverity.Error)
.Show();
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", $"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.");
return;
}
@ -215,11 +208,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
}
catch (Exception e)
{
_notificationService.CreateNotification()
.WithMessage($"Failed to enable '{FeatureInfo.Name}'.\r\n{e.Message}")
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.WithSeverity(NotificationSeverity.Error)
.Show();
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", e.Message);
}
finally
{
@ -254,4 +243,17 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
{
this.RaisePropertyChanged(nameof(CanToggleEnabled));
}
private async Task ShowFailureDialog(string action, string message)
{
ContentDialogBuilder builder = _windowService.CreateContentDialog()
.WithTitle(action)
.WithContent(message)
.HavingPrimaryButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder));
// If available, add a secondary button pointing to the support page
if (FeatureInfo.Plugin.Info.HelpPage != null)
builder = builder.HavingSecondaryButton(b => b.WithText("Open support page").WithAction(() => Utilities.OpenUrl(FeatureInfo.Plugin.Info.HelpPage.ToString())));
await builder.ShowAsync();
}
}

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Screens.Plugins.Features;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using ReactiveUI;

View File

@ -3,10 +3,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsWindowView"
x:DataType="plugins:PluginSettingsWindowViewModel"
Icon="/Assets/Images/Logo/application.ico"
Title="{Binding DisplayName}"
Title="{CompiledBinding DisplayName}"
Width="800"
Height="800"
WindowStartupLocation="CenterOwner">

View File

@ -46,9 +46,9 @@
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,Auto">
<StackPanel Orientation="Horizontal">
<SplitButton Content="Settings" Command="{CompiledBinding OpenSettings}">
<SplitButton.Flyout>
<StackPanel Orientation="Horizontal" Spacing="5">
<DropDownButton Content="Manage">
<DropDownButton.Flyout>
<MenuFlyout Placement="Bottom" Opening="FlyoutBase_OnOpening">
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
<MenuItem.Icon>
@ -70,6 +70,7 @@
<avalonia:MaterialIcon Kind="Delete" />
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem Header="Clear plugin settings" Command="{CompiledBinding RemoveSettings}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="DatabaseRemove" />
@ -81,19 +82,31 @@
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</SplitButton.Flyout>
</SplitButton>
</DropDownButton.Flyout>
</DropDownButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}"
Command="{CompiledBinding OpenSettings}"
ToolTip.Tip="Open settings">
<avalonia:MaterialIcon Kind="Cog" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.Info.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.HelpPage}"
ToolTip.Tip="{CompiledBinding Plugin.Info.HelpPage}">
<avalonia:MaterialIcon Kind="HelpCircle" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
Margin="5 0"
IsVisible="{CompiledBinding Plugin.Info.Website, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Website}">
NavigateUri="{CompiledBinding Plugin.Info.Website}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Website}">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
Margin="5 0"
IsVisible="{CompiledBinding Plugin.Info.Repository, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Repository}">
NavigateUri="{CompiledBinding Plugin.Info.Repository}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Repository}">
<avalonia:MaterialIcon Kind="Git" />
</controls:HyperlinkButton>
</StackPanel>

View File

@ -28,7 +28,7 @@ public class PluginViewModel : ActivatableViewModelBase
private bool _canRemovePrerequisites;
private bool _enabling;
private Plugin _plugin;
private Window? _window;
private Window? _settingsWindow;
public PluginViewModel(Plugin plugin,
ReactiveCommand<Unit, Unit>? reload,
@ -72,7 +72,7 @@ public class PluginViewModel : ActivatableViewModelBase
{
Plugin.Enabled -= OnPluginToggled;
Plugin.Disabled -= OnPluginToggled;
_window?.Close();
_settingsWindow?.Close();
}).DisposeWith(d);
});
}
@ -128,11 +128,7 @@ public class PluginViewModel : ActivatableViewModelBase
}
catch (Exception e)
{
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
.WithSeverity(NotificationSeverity.Error)
.WithMessage($"Failed to disable plugin {Plugin.Info.Name}\r\n{e.Message}")
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.Show());
await ShowUpdateEnableFailure(enable, e);
}
finally
{
@ -167,11 +163,7 @@ public class PluginViewModel : ActivatableViewModelBase
}
catch (Exception e)
{
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
.WithSeverity(NotificationSeverity.Error)
.WithMessage($"Failed to enable plugin {Plugin.Info.Name}\r\n{e.Message}")
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.Show());
await ShowUpdateEnableFailure(enable, e);
}
finally
{
@ -180,7 +172,6 @@ public class PluginViewModel : ActivatableViewModelBase
}
}
public void CheckPrerequisites()
{
CanInstallPrerequisites = false;
@ -199,10 +190,10 @@ public class PluginViewModel : ActivatableViewModelBase
if (Plugin.ConfigurationDialog == null)
return;
if (_window != null)
if (_settingsWindow != null)
{
_window.WindowState = WindowState.Normal;
_window.Activate();
_settingsWindow.WindowState = WindowState.Normal;
_settingsWindow.Activate();
return;
}
@ -211,8 +202,8 @@ public class PluginViewModel : ActivatableViewModelBase
if (Plugin.Resolve(Plugin.ConfigurationDialog.Type) is not PluginConfigurationViewModel viewModel)
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
_window = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
_window.Closed += (_, _) => _window = null;
_settingsWindow = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
_settingsWindow.Closed += (_, _) => _settingsWindow = null;
}
catch (Exception e)
{
@ -306,6 +297,20 @@ public class PluginViewModel : ActivatableViewModelBase
_windowService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
}
}
private async Task ShowUpdateEnableFailure(bool enable, Exception e)
{
string action = enable ? "enable" : "disable";
ContentDialogBuilder builder = _windowService.CreateContentDialog()
.WithTitle($"Failed to {action} plugin {Plugin.Info.Name}")
.WithContent(e.Message)
.HavingPrimaryButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder));
// If available, add a secondary button pointing to the support page
if (Plugin.Info.HelpPage != null)
builder = builder.HavingSecondaryButton(b => b.WithText("Open support page").WithAction(() => Utilities.OpenUrl(Plugin.Info.HelpPage.ToString())));
await builder.ShowAsync();
}
private void OnPluginToggled(object? sender, EventArgs e)
{
@ -313,7 +318,7 @@ public class PluginViewModel : ActivatableViewModelBase
{
this.RaisePropertyChanged(nameof(IsEnabled));
if (!IsEnabled)
_window?.Close();
_settingsWindow?.Close();
});
}
}

View File

@ -3,9 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisiteActionView"
x:DataType="plugins:PluginPrerequisiteActionViewModel">
x:Class="Artemis.UI.Screens.Plugins.Prerequisites.PluginPrerequisiteActionView"
x:DataType="prerequisites:PluginPrerequisiteActionViewModel">
<StackPanel>
<ProgressBar Value="{CompiledBinding Action.Progress.Percentage, Mode=OneWay}"
IsIndeterminate="{CompiledBinding Action.ProgressIndeterminate, Mode=OneWay}"

View File

@ -1,7 +1,6 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Prerequisites;
public partial class PluginPrerequisiteActionView : UserControl
{

View File

@ -1,7 +1,7 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Prerequisites;
public class PluginPrerequisiteActionViewModel : ViewModelBase
{

View File

@ -3,9 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisiteView"
x:DataType="plugins:PluginPrerequisiteViewModel">
x:Class="Artemis.UI.Screens.Plugins.Prerequisites.PluginPrerequisiteView"
x:DataType="prerequisites:PluginPrerequisiteViewModel">
<StackPanel>
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Name, Mode=OneWay}" />
<TextBlock Classes="subtitle" TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Description, Mode=OneWay}" Margin="0 0 0 15" />

View File

@ -1,7 +1,6 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Prerequisites;
public partial class PluginPrerequisiteView : ReactiveUserControl<PluginPrerequisiteViewModel>
{

View File

@ -8,7 +8,7 @@ using Artemis.Core;
using Artemis.UI.Shared;
using ReactiveUI;
namespace Artemis.UI.Screens.Plugins;
namespace Artemis.UI.Screens.Plugins.Prerequisites;
public class PluginPrerequisiteViewModel : ActivatableViewModelBase
{

View File

@ -4,9 +4,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:updating="clr-namespace:Artemis.UI.Screens.Settings.Updating"
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
xmlns:mdc="clr-namespace:Markdown.Avalonia.Controls;assembly=Markdown.Avalonia"
xmlns:mde="clr-namespace:Markdown.Avalonia.Extensions;assembly=Markdown.Avalonia"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
xmlns:avalonia1="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="1400"
@ -158,17 +155,7 @@
<avalonia:MarkdownScrollViewer Grid.Row="2" Markdown="{CompiledBinding Changelog}" MarkdownStyleName="FluentAvalonia">
<avalonia:MarkdownScrollViewer.Styles>
<Style Selector="ctxt|CHyperlink">
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight3}" />
</Style>
<Style Selector="ctxt|CHyperlink:pointerover">
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight1}" />
</Style>
<Style Selector="Grid.List">
<Style.Setters>
<Setter Property="Margin" Value="20,0,0,0"/>
</Style.Setters>
</Style>
<StyleInclude Source="/Styles/Markdown.axaml"/>
</avalonia:MarkdownScrollViewer.Styles>
</avalonia:MarkdownScrollViewer>
</Grid>

View File

@ -0,0 +1,60 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia">
<Style Selector="ctxt|CHyperlink">
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight3}" />
</Style>
<Style Selector="ctxt|CHyperlink:pointerover">
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight1}" />
</Style>
<Style Selector="Grid.List">
<Style.Setters>
<Setter Property="Margin" Value="10,0,0,0" />
</Style.Setters>
</Style>
<Style Selector="ctxt|CTextBlock">
<Style.Setters>
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="0,5" />
</Style.Setters>
</Style>
<Style Selector="TextBlock">
<Style.Setters>
<Setter Property="FontSize" Value="14" />
</Style.Setters>
</Style>
<Style Selector="ctxt|CTextBlock.Heading1">
<Style.Setters>
<Setter Property="FontSize" Value="28" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Margin" Value="0,15,0,5" />
</Style.Setters>
</Style>
<Style Selector="ctxt|CTextBlock.Heading2">
<Style.Setters>
<Setter Property="FontSize" Value="22" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Margin" Value="0,15,0,5" />
</Style.Setters>
</Style>
<Style Selector="ctxt|CTextBlock.Heading3">
<Style.Setters>
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Margin" Value="0,10,0,5" />
</Style.Setters>
</Style>
<Style Selector="ctxt|CTextBlock.Heading4">
<Style.Setters>
<Setter Property="FontSize" Value="14" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Margin" Value="0,10,0,5" />
</Style.Setters>
</Style>
</Styles>