mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Use a help page URL instead of doing things in-app
This commit is contained in:
parent
949106e470
commit
2b15657f8d
@ -45,30 +45,8 @@ public class ArtemisPluginException : Exception
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
|
|
||||||
/// </summary>
|
|
||||||
public ArtemisPluginException(string message, string helpPageId) : base(message)
|
|
||||||
{
|
|
||||||
HelpPageId = helpPageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
|
|
||||||
/// </summary>
|
|
||||||
public ArtemisPluginException(string message, Exception inner, string helpPageId) : base(message, inner)
|
|
||||||
{
|
|
||||||
HelpPageId = helpPageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the error is related to
|
/// Gets the plugin the error is related to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin? Plugin { get; }
|
public Plugin? Plugin { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the ID of the help page to display for this exception.
|
|
||||||
/// </summary>
|
|
||||||
public string? HelpPageId { get; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,22 +0,0 @@
|
|||||||
namespace Artemis.Core;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a plugin related help page
|
|
||||||
/// </summary>
|
|
||||||
public interface IPluginHelpPage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the plugin the help page belongs to.
|
|
||||||
/// </summary>
|
|
||||||
Plugin Plugin { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the title of the help page.
|
|
||||||
/// </summary>
|
|
||||||
public string Title { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An ID used to quickly lead users to the help page in case of an error.
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; }
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Artemis.Core;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a plugin related help page
|
|
||||||
/// </summary>
|
|
||||||
public class MarkdownPluginHelpPage : IPluginHelpPage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the <see cref="MarkdownPluginHelpPage" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="plugin">The plugin to display the markdown for.</param>
|
|
||||||
/// <param name="markdownFile">A file path relative to the plugin or absolute, pointing to the markdown to display</param>
|
|
||||||
/// <param name="id">The ID of the help page, used to quickly lead users to it in case of errors.</param>
|
|
||||||
/// <exception cref="FileNotFoundException"></exception>
|
|
||||||
public MarkdownPluginHelpPage(Plugin plugin, string title, string id, string markdownFile)
|
|
||||||
{
|
|
||||||
Plugin = plugin;
|
|
||||||
Title = title;
|
|
||||||
Id = id;
|
|
||||||
MarkdownFile = Path.IsPathRooted(markdownFile) ? markdownFile : Plugin.ResolveRelativePath(markdownFile);
|
|
||||||
|
|
||||||
if (!File.Exists(MarkdownFile))
|
|
||||||
throw new FileNotFoundException($"Could not find markdown file at \"{MarkdownFile}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Plugin Plugin { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string Title { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the absolute path to the markdown that is to be displayed.
|
|
||||||
/// </summary>
|
|
||||||
public string MarkdownFile { get; }
|
|
||||||
}
|
|
||||||
@ -36,7 +36,6 @@ public class Plugin : CorePropertyChanged, IDisposable
|
|||||||
|
|
||||||
Features = new ReadOnlyCollection<PluginFeatureInfo>(_features);
|
Features = new ReadOnlyCollection<PluginFeatureInfo>(_features);
|
||||||
Profilers = new ReadOnlyCollection<Profiler>(_profilers);
|
Profilers = new ReadOnlyCollection<Profiler>(_profilers);
|
||||||
HelpPages = new List<IPluginHelpPage>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -59,8 +58,6 @@ public class Plugin : CorePropertyChanged, IDisposable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IPluginConfigurationDialog? ConfigurationDialog { get; set; }
|
public IPluginConfigurationDialog? ConfigurationDialog { get; set; }
|
||||||
|
|
||||||
public List<IPluginHelpPage> HelpPages { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the user enabled the plugin or not
|
/// Indicates whether the user enabled the plugin or not
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
private bool _requiresAdmin;
|
private bool _requiresAdmin;
|
||||||
private string _version = null!;
|
private string _version = null!;
|
||||||
private Uri? _website;
|
private Uri? _website;
|
||||||
|
private Uri? _helpPage;
|
||||||
|
|
||||||
internal PluginInfo()
|
internal PluginInfo()
|
||||||
{
|
{
|
||||||
@ -92,6 +93,16 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
set => SetAndNotify(ref _repository, value);
|
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>
|
/// <summary>
|
||||||
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
||||||
/// available icons
|
/// available icons
|
||||||
@ -188,9 +199,6 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty]
|
|
||||||
internal List<PluginInfoHelpPage> HelpPages { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether this plugin is compatible with the current operating system and API version
|
/// Gets a boolean indicating whether this plugin is compatible with the current operating system and API version
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Artemis.Core;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents basic info about a plugin and contains a reference to the instance of said plugin
|
|
||||||
/// </summary>
|
|
||||||
internal class PluginInfoHelpPage
|
|
||||||
{
|
|
||||||
[JsonConstructor]
|
|
||||||
public PluginInfoHelpPage(string title, string markdownFile, string id)
|
|
||||||
{
|
|
||||||
Title = title;
|
|
||||||
MarkdownFile = markdownFile;
|
|
||||||
Id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty(Required = Required.Always)]
|
|
||||||
public string Title { get; }
|
|
||||||
|
|
||||||
[JsonProperty(Required = Required.Always)]
|
|
||||||
public string MarkdownFile { get; }
|
|
||||||
|
|
||||||
[JsonProperty(Required = Required.Always)]
|
|
||||||
public string Id { get; }
|
|
||||||
}
|
|
||||||
@ -350,9 +350,6 @@ internal class PluginManagementService : IPluginManagementService
|
|||||||
|
|
||||||
// Load the entity and fall back on creating a new one
|
// Load the entity and fall back on creating a new one
|
||||||
Plugin plugin = new(pluginInfo, directory, _pluginRepository.GetPluginByGuid(pluginInfo.Guid));
|
Plugin plugin = new(pluginInfo, directory, _pluginRepository.GetPluginByGuid(pluginInfo.Guid));
|
||||||
foreach (PluginInfoHelpPage pluginInfoHelpPage in pluginInfo.HelpPages)
|
|
||||||
plugin.HelpPages.Add(new MarkdownPluginHelpPage(plugin, pluginInfoHelpPage.Title, pluginInfoHelpPage.Id, pluginInfoHelpPage.MarkdownFile));
|
|
||||||
|
|
||||||
OnPluginLoading(new PluginEventArgs(plugin));
|
OnPluginLoading(new PluginEventArgs(plugin));
|
||||||
|
|
||||||
// Locate the main assembly entry
|
// Locate the main assembly entry
|
||||||
|
|||||||
@ -52,14 +52,6 @@
|
|||||||
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Screens\Plugins\Help\MarkdownPluginHelpPageView.axaml.cs">
|
|
||||||
<DependentUpon>MarkdownPluginHelpPageView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Plugins\Help\PluginHelpWindowView.axaml.cs">
|
|
||||||
<DependentUpon>PluginHelpWindowView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Plugins\Features\PluginFeatureView.axaml.cs">
|
<Compile Update="Screens\Plugins\Features\PluginFeatureView.axaml.cs">
|
||||||
<DependentUpon>PluginFeatureView.axaml</DependentUpon>
|
<DependentUpon>PluginFeatureView.axaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
|
|||||||
@ -23,7 +23,6 @@ namespace Artemis.UI.Screens.Plugins.Features;
|
|||||||
public class PluginFeatureViewModel : ActivatableViewModelBase
|
public class PluginFeatureViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
private readonly INotificationService _notificationService;
|
|
||||||
private readonly IPluginManagementService _pluginManagementService;
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private bool _enabling;
|
private bool _enabling;
|
||||||
@ -32,12 +31,10 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
bool showShield,
|
bool showShield,
|
||||||
ICoreService coreService,
|
ICoreService coreService,
|
||||||
IWindowService windowService,
|
IWindowService windowService,
|
||||||
INotificationService notificationService,
|
|
||||||
IPluginManagementService pluginManagementService)
|
IPluginManagementService pluginManagementService)
|
||||||
{
|
{
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_notificationService = notificationService;
|
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
|
|
||||||
FeatureInfo = pluginFeatureInfo;
|
FeatureInfo = pluginFeatureInfo;
|
||||||
@ -176,11 +173,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
if (FeatureInfo.Instance == null)
|
if (FeatureInfo.Instance == null)
|
||||||
{
|
{
|
||||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||||
_notificationService.CreateNotification()
|
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", $"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.");
|
||||||
.WithMessage($"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.Show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +208,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_notificationService.CreateNotification()
|
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", e.Message);
|
||||||
.WithMessage($"Failed to enable '{FeatureInfo.Name}'.\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.Show();
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -254,4 +243,17 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
this.RaisePropertyChanged(nameof(CanToggleEnabled));
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
|
|
||||||
xmlns:help="clr-namespace:Artemis.UI.Screens.Plugins.Help"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
|
||||||
x:Class="Artemis.UI.Screens.Plugins.Help.MarkdownPluginHelpPageView"
|
|
||||||
x:DataType="help:MarkdownPluginHelpPageViewModel">
|
|
||||||
<avalonia:MarkdownScrollViewer Markdown="{CompiledBinding MarkdownText}" MarkdownStyleName="FluentAvalonia">
|
|
||||||
<avalonia:MarkdownScrollViewer.Styles>
|
|
||||||
<StyleInclude Source="/Styles/Markdown.axaml"/>
|
|
||||||
</avalonia:MarkdownScrollViewer.Styles>
|
|
||||||
</avalonia:MarkdownScrollViewer>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins.Help;
|
|
||||||
|
|
||||||
public partial class MarkdownPluginHelpPageView : ReactiveUserControl<MarkdownPluginHelpPageViewModel>
|
|
||||||
{
|
|
||||||
public MarkdownPluginHelpPageView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
AvaloniaXamlLoader.Load(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins.Help;
|
|
||||||
|
|
||||||
public class MarkdownPluginHelpPageViewModel : ActivatableViewModelBase, IPluginHelpPage
|
|
||||||
{
|
|
||||||
private readonly MarkdownPluginHelpPage _helpPage;
|
|
||||||
private string? _markdownText;
|
|
||||||
|
|
||||||
public MarkdownPluginHelpPageViewModel(MarkdownPluginHelpPage helpPage)
|
|
||||||
{
|
|
||||||
_helpPage = helpPage;
|
|
||||||
this.WhenActivated(d =>
|
|
||||||
{
|
|
||||||
FileSystemWatcher watcher = new();
|
|
||||||
watcher.Path = Path.GetDirectoryName(_helpPage.MarkdownFile) ?? throw new InvalidOperationException($"Path \"{_helpPage.MarkdownFile}\" does not contain a directory");
|
|
||||||
watcher.Filter = Path.GetFileName(_helpPage.MarkdownFile);
|
|
||||||
watcher.EnableRaisingEvents = true;
|
|
||||||
watcher.Changed += WatcherOnChanged;
|
|
||||||
watcher.DisposeWith(d);
|
|
||||||
|
|
||||||
LoadMarkdown().DisposeWith(d);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public string? MarkdownText
|
|
||||||
{
|
|
||||||
get => _markdownText;
|
|
||||||
set => RaiseAndSetIfChanged(ref _markdownText, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void WatcherOnChanged(object sender, FileSystemEventArgs e)
|
|
||||||
{
|
|
||||||
await LoadMarkdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadMarkdown()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await using FileStream stream = new(_helpPage.MarkdownFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
|
||||||
using StreamReader reader = new(stream);
|
|
||||||
MarkdownText = await reader.ReadToEndAsync();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
MarkdownText = e.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Plugin Plugin => _helpPage.Plugin;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string Title => _helpPage.Title;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string Id => _helpPage.Id;
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
<Window xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
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:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
|
||||||
xmlns:help="clr-namespace:Artemis.UI.Screens.Plugins.Help"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
|
||||||
x:Class="Artemis.UI.Screens.Plugins.Help.PluginHelpWindowView"
|
|
||||||
x:DataType="help:PluginHelpWindowViewModel"
|
|
||||||
Icon="/Assets/Images/Logo/application.ico"
|
|
||||||
Title="{CompiledBinding DisplayName}"
|
|
||||||
Width="1200"
|
|
||||||
Height="800"
|
|
||||||
WindowStartupLocation="CenterOwner">
|
|
||||||
|
|
||||||
<Grid ColumnDefinitions="240,*">
|
|
||||||
<ListBox Items="{CompiledBinding HelpPages}" SelectedItem="{CompiledBinding SelectedHelpPage}" Grid.Column="0" Margin="10">
|
|
||||||
<ListBox.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="core:IPluginHelpPage">
|
|
||||||
<TextBlock Text="{CompiledBinding Title}" VerticalAlignment="Center" />
|
|
||||||
</DataTemplate>
|
|
||||||
</ListBox.ItemTemplate>
|
|
||||||
</ListBox>
|
|
||||||
<Border Classes="router-container" Grid.Column="1">
|
|
||||||
<ContentControl Content="{CompiledBinding SelectedHelpPage}" Margin="15"></ContentControl>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Classes="notification-container" Name="NotificationContainer" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
|
|
||||||
</Grid>
|
|
||||||
</Window>
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
using Artemis.UI.Shared;
|
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins.Help;
|
|
||||||
|
|
||||||
public partial class PluginHelpWindowView : ReactiveAppWindow<PluginHelpWindowViewModel>
|
|
||||||
{
|
|
||||||
public PluginHelpWindowView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
#if DEBUG
|
|
||||||
this.AttachDevTools();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
AvaloniaXamlLoader.Load(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins.Help;
|
|
||||||
|
|
||||||
public class PluginHelpWindowViewModel : ActivatableViewModelBase
|
|
||||||
{
|
|
||||||
private IPluginHelpPage? _selectedHelpPage;
|
|
||||||
|
|
||||||
public PluginHelpWindowViewModel(Plugin plugin, string? preselectId)
|
|
||||||
{
|
|
||||||
Plugin = plugin;
|
|
||||||
DisplayName = $"{Plugin.Info.Name} | Help";
|
|
||||||
|
|
||||||
// Populate help pages by wrapping MarkdownHelpPages into a MarkdownHelpPageViewModel
|
|
||||||
// other types are used directly, up to them to implement a VM directly as well
|
|
||||||
HelpPages = new ReadOnlyCollection<IPluginHelpPage>(plugin.HelpPages.Select(p => p is MarkdownPluginHelpPage m ? new MarkdownPluginHelpPageViewModel(m) : p).ToList());
|
|
||||||
|
|
||||||
_selectedHelpPage = preselectId != null ? HelpPages.FirstOrDefault(p => p.Id == preselectId) : HelpPages.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugin Plugin { get; }
|
|
||||||
public ReadOnlyCollection<IPluginHelpPage> HelpPages { get; }
|
|
||||||
|
|
||||||
public IPluginHelpPage? SelectedHelpPage
|
|
||||||
{
|
|
||||||
get => _selectedHelpPage;
|
|
||||||
set => RaiseAndSetIfChanged(ref _selectedHelpPage, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -92,9 +92,9 @@
|
|||||||
<avalonia:MaterialIcon Kind="Cog" />
|
<avalonia:MaterialIcon Kind="Cog" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
IsVisible="{CompiledBinding HasHelpPages}"
|
IsVisible="{CompiledBinding Plugin.Info.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
Command="{CompiledBinding OpenHelp}"
|
NavigateUri="{CompiledBinding Plugin.Info.HelpPage}"
|
||||||
ToolTip.Tip="View help pages">
|
ToolTip.Tip="{CompiledBinding Plugin.Info.HelpPage}">
|
||||||
<avalonia:MaterialIcon Kind="HelpCircle" />
|
<avalonia:MaterialIcon Kind="HelpCircle" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
|
|||||||
@ -4,12 +4,10 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Screens.Plugins.Help;
|
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.Builders;
|
using Artemis.UI.Shared.Services.Builders;
|
||||||
@ -31,7 +29,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
private bool _enabling;
|
private bool _enabling;
|
||||||
private Plugin _plugin;
|
private Plugin _plugin;
|
||||||
private Window? _settingsWindow;
|
private Window? _settingsWindow;
|
||||||
private Window? _helpWindow;
|
|
||||||
|
|
||||||
public PluginViewModel(Plugin plugin,
|
public PluginViewModel(Plugin plugin,
|
||||||
ReactiveCommand<Unit, Unit>? reload,
|
ReactiveCommand<Unit, Unit>? reload,
|
||||||
@ -59,7 +56,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
Reload = reload;
|
Reload = reload;
|
||||||
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin.ConfigurationDialog != null));
|
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin.ConfigurationDialog != null));
|
||||||
OpenHelp = ReactiveCommand.Create(ExecuteOpenHelp, this.WhenAnyValue(vm => vm.HasHelpPages));
|
|
||||||
RemoveSettings = ReactiveCommand.CreateFromTask(ExecuteRemoveSettings);
|
RemoveSettings = ReactiveCommand.CreateFromTask(ExecuteRemoveSettings);
|
||||||
Remove = ReactiveCommand.CreateFromTask(ExecuteRemove);
|
Remove = ReactiveCommand.CreateFromTask(ExecuteRemove);
|
||||||
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
||||||
@ -77,14 +73,12 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
Plugin.Enabled -= OnPluginToggled;
|
Plugin.Enabled -= OnPluginToggled;
|
||||||
Plugin.Disabled -= OnPluginToggled;
|
Plugin.Disabled -= OnPluginToggled;
|
||||||
_settingsWindow?.Close();
|
_settingsWindow?.Close();
|
||||||
_helpWindow?.Close();
|
|
||||||
}).DisposeWith(d);
|
}).DisposeWith(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit>? Reload { get; }
|
public ReactiveCommand<Unit, Unit>? Reload { get; }
|
||||||
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
||||||
public ReactiveCommand<Unit,Unit> OpenHelp { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> RemoveSettings { get; }
|
public ReactiveCommand<Unit, Unit> RemoveSettings { get; }
|
||||||
public ReactiveCommand<Unit, Unit> Remove { get; }
|
public ReactiveCommand<Unit, Unit> Remove { get; }
|
||||||
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
||||||
@ -108,7 +102,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
||||||
public bool IsEnabled => Plugin.IsEnabled;
|
public bool IsEnabled => Plugin.IsEnabled;
|
||||||
public bool HasHelpPages => Plugin.HelpPages.Any();
|
|
||||||
|
|
||||||
public bool CanInstallPrerequisites
|
public bool CanInstallPrerequisites
|
||||||
{
|
{
|
||||||
@ -135,11 +128,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
|
await ShowUpdateEnableFailure(enable, e);
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.WithMessage($"Failed to disable plugin {Plugin.Info.Name}\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.Show());
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -174,11 +163,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
|
await ShowUpdateEnableFailure(enable, e);
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.WithMessage($"Failed to enable plugin {Plugin.Info.Name}\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.Show());
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -187,7 +172,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void CheckPrerequisites()
|
public void CheckPrerequisites()
|
||||||
{
|
{
|
||||||
CanInstallPrerequisites = false;
|
CanInstallPrerequisites = false;
|
||||||
@ -228,27 +212,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteOpenHelp()
|
|
||||||
{
|
|
||||||
if (_helpWindow != null)
|
|
||||||
{
|
|
||||||
_helpWindow.WindowState = WindowState.Normal;
|
|
||||||
_helpWindow.Activate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_helpWindow = _windowService.ShowWindow(new PluginHelpWindowViewModel(Plugin, null));
|
|
||||||
_helpWindow.Closed += (_, _) => _helpWindow = null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_windowService.ShowExceptionDialog("An exception occured while trying to show the plugin's help window", e);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteOpenPluginDirectory()
|
private void ExecuteOpenPluginDirectory()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -335,6 +298,20 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private void OnPluginToggled(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user