mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Setup wizard - Added and auto-show on home open
UI - Slightly darkened W11 effect
This commit is contained in:
1 parent
5c1da6d2c4
commit
1210dc3f63
37 files changed
+1177
-487
No files matched your search
@@ -2,127 +2,15 @@
|
||||
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:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsView"
|
||||
x:DataType="plugins:PluginSettingsViewModel">
|
||||
<Border Classes="card" Padding="15" Margin="0 5">
|
||||
<Grid RowDefinitions="*,Auto" ColumnDefinitions="4*,5*">
|
||||
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*, Auto">
|
||||
<shared:ArtemisIcon Icon="{CompiledBinding Plugin.Info.ResolvedIcon}"
|
||||
Fill="False"
|
||||
Width="48"
|
||||
Height="48"
|
||||
Margin="0 5 0 0"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="3"
|
||||
VerticalAlignment="Top" />
|
||||
<Grid ColumnDefinitions="4*,5*">
|
||||
<ContentControl Grid.Column="0" Content="{CompiledBinding PluginViewModel}" />
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="0" Classes="h5 no-margin" Text="{CompiledBinding Plugin.Info.Name}" />
|
||||
|
||||
<ItemsControl Grid.Column="2" Grid.Row="0" IsVisible="{CompiledBinding Platforms.Count}" Items="{CompiledBinding Platforms}" HorizontalAlignment="Right">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="5" Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="1"
|
||||
Classes="subtitle"
|
||||
Text="{CompiledBinding Plugin.Info.Author}"
|
||||
IsVisible="{CompiledBinding Plugin.Info.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0 5"
|
||||
Text="{CompiledBinding Plugin.Info.Description}" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="0" ColumnDefinitions="*,Auto">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<controls:SplitButton Content="Settings" Command="{CompiledBinding OpenSettings}">
|
||||
<controls:SplitButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom" IsOpen="{CompiledBinding IsSettingsPopupOpen, Mode=OneWayToSource}">
|
||||
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="FolderOpen" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Reload plugin" Command="{CompiledBinding Reload}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Reload" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Install prerequisites" Command="{CompiledBinding InstallPrerequisites}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="CheckAll" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Remove prerequisites" Command="{CompiledBinding RemovePrerequisites}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Delete" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Clear plugin settings" Command="{CompiledBinding RemoveSettings}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="DatabaseRemove" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Remove plugin" Command="{CompiledBinding Remove}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="DeleteForever" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</controls:SplitButton.Flyout>
|
||||
</controls:SplitButton>
|
||||
|
||||
<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}">
|
||||
<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}">
|
||||
<avalonia:MaterialIcon Kind="Git" />
|
||||
</controls:HyperlinkButton>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Name="EnabledToggle"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{CompiledBinding !Enabling}"
|
||||
IsChecked="{CompiledBinding IsEnabled, Mode=OneWay}"
|
||||
IsEnabled="{CompiledBinding Plugin.Info.IsCompatible}">
|
||||
<StackPanel x:Name="EnableText" Orientation="Horizontal">
|
||||
<TextBlock>Enable plugin</TextBlock>
|
||||
<avalonia:MaterialIcon Kind="ShieldHalfFull"
|
||||
Margin="5 0 0 0"
|
||||
ToolTip.Tip="Plugin requires admin rights"
|
||||
IsVisible="{CompiledBinding Plugin.Info.RequiresAdmin}" />
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
|
||||
<ProgressBar Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{CompiledBinding Enabling}"
|
||||
IsIndeterminate="True" />
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
|
||||
<Border Grid.Column="1" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<TextBlock Classes="h5">Plugin features</TextBlock>
|
||||
<ListBox Grid.Row="1" MaxHeight="135" Items="{CompiledBinding PluginFeatures}" />
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.UI.Screens.Plugins
|
||||
{
|
||||
public partial class PluginSettingsView : ReactiveUserControl<PluginSettingsViewModel>
|
||||
{
|
||||
private readonly CheckBox _enabledToggle;
|
||||
|
||||
public PluginSettingsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_enabledToggle = this.Find<CheckBox>("EnabledToggle");
|
||||
_enabledToggle.Click += EnabledToggleOnClick;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void EnabledToggleOnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => ViewModel?.UpdateEnabled(!ViewModel.Plugin.IsEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,358 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using Material.Icons;
|
||||
using Material.Icons.Avalonia;
|
||||
using Ninject;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Plugins;
|
||||
|
||||
public class PluginSettingsViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||
private readonly IWindowService _windowService;
|
||||
private bool _canInstallPrerequisites;
|
||||
private bool _canRemovePrerequisites;
|
||||
private bool _enabling;
|
||||
private bool _isSettingsPopupOpen;
|
||||
private Plugin _plugin;
|
||||
private Window? _window;
|
||||
|
||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly INotificationService _notificationService;
|
||||
|
||||
private PluginViewModel _pluginViewModel;
|
||||
|
||||
public PluginSettingsViewModel(Plugin plugin,
|
||||
ISettingsVmFactory settingsVmFactory,
|
||||
ICoreService coreService,
|
||||
IWindowService windowService,
|
||||
INotificationService notificationService,
|
||||
IPluginManagementService pluginManagementService)
|
||||
public PluginSettingsViewModel(Plugin plugin, ISettingsVmFactory settingsVmFactory, IPluginManagementService pluginManagementService, INotificationService notificationService)
|
||||
{
|
||||
_plugin = plugin;
|
||||
|
||||
_settingsVmFactory = settingsVmFactory;
|
||||
_coreService = coreService;
|
||||
_windowService = windowService;
|
||||
_notificationService = notificationService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
PluginFeatures = new ObservableCollection<PluginFeatureViewModel>();
|
||||
foreach (PluginFeatureInfo pluginFeatureInfo in Plugin.Features)
|
||||
PluginFeatures.Add(_settingsVmFactory.CreatePluginFeatureViewModel(pluginFeatureInfo, false));
|
||||
|
||||
Platforms = new ObservableCollection<PluginPlatformViewModel>();
|
||||
if (Plugin.Info.Platforms != null)
|
||||
{
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.Windows))
|
||||
Platforms.Add(new PluginPlatformViewModel("Windows", MaterialIconKind.MicrosoftWindows));
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.Linux))
|
||||
Platforms.Add(new PluginPlatformViewModel("Linux", MaterialIconKind.Linux));
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.OSX))
|
||||
Platforms.Add(new PluginPlatformViewModel("OSX", MaterialIconKind.Apple));
|
||||
}
|
||||
_notificationService = notificationService;
|
||||
|
||||
Reload = ReactiveCommand.CreateFromTask(ExecuteReload);
|
||||
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin.ConfigurationDialog != null));
|
||||
RemoveSettings = ReactiveCommand.CreateFromTask(ExecuteRemoveSettings);
|
||||
Remove = ReactiveCommand.CreateFromTask(ExecuteRemove);
|
||||
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
||||
RemovePrerequisites = ReactiveCommand.CreateFromTask<bool>(ExecuteRemovePrerequisites, this.WhenAnyValue(x => x.CanRemovePrerequisites));
|
||||
ShowLogsFolder = ReactiveCommand.Create(ExecuteShowLogsFolder);
|
||||
OpenPluginDirectory = ReactiveCommand.Create(ExecuteOpenPluginDirectory);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
Plugin.Enabled += OnPluginToggled;
|
||||
Plugin.Disabled += OnPluginToggled;
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
Plugin.Enabled -= OnPluginToggled;
|
||||
Plugin.Disabled -= OnPluginToggled;
|
||||
_window?.Close();
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
|
||||
PluginViewModel = settingsVmFactory.PluginViewModel(_plugin, Reload);
|
||||
PluginFeatures = new ObservableCollection<PluginFeatureViewModel>();
|
||||
foreach (PluginFeatureInfo pluginFeatureInfo in _plugin.Features)
|
||||
PluginFeatures.Add(settingsVmFactory.PluginFeatureViewModel(pluginFeatureInfo, false));
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit> Reload { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> RemoveSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> Remove { get; }
|
||||
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
||||
public ReactiveCommand<bool, Unit> RemovePrerequisites { get; }
|
||||
public ReactiveCommand<Unit, Unit> ShowLogsFolder { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenPluginDirectory { get; }
|
||||
|
||||
public PluginViewModel PluginViewModel
|
||||
{
|
||||
get => _pluginViewModel;
|
||||
private set => RaiseAndSetIfChanged(ref _pluginViewModel, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<PluginFeatureViewModel> PluginFeatures { get; }
|
||||
public ObservableCollection<PluginPlatformViewModel> Platforms { get; }
|
||||
|
||||
public Plugin Plugin
|
||||
{
|
||||
get => _plugin;
|
||||
set => RaiseAndSetIfChanged(ref _plugin, value);
|
||||
}
|
||||
|
||||
public bool Enabling
|
||||
{
|
||||
get => _enabling;
|
||||
set => RaiseAndSetIfChanged(ref _enabling, value);
|
||||
}
|
||||
|
||||
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
||||
public bool IsEnabled => Plugin.IsEnabled;
|
||||
|
||||
public bool IsSettingsPopupOpen
|
||||
{
|
||||
get => _isSettingsPopupOpen;
|
||||
set
|
||||
{
|
||||
if (!RaiseAndSetIfChanged(ref _isSettingsPopupOpen, value)) return;
|
||||
CheckPrerequisites();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanInstallPrerequisites
|
||||
{
|
||||
get => _canInstallPrerequisites;
|
||||
set => RaiseAndSetIfChanged(ref _canInstallPrerequisites, value);
|
||||
}
|
||||
|
||||
public bool CanRemovePrerequisites
|
||||
{
|
||||
get => _canRemovePrerequisites;
|
||||
set => RaiseAndSetIfChanged(ref _canRemovePrerequisites, value);
|
||||
}
|
||||
|
||||
private void ExecuteOpenSettings()
|
||||
{
|
||||
if (Plugin.ConfigurationDialog == null)
|
||||
return;
|
||||
|
||||
if (_window != null)
|
||||
{
|
||||
_window.WindowState = WindowState.Normal;
|
||||
_window.Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PluginConfigurationViewModel? viewModel = Plugin.Kernel!.Get(Plugin.ConfigurationDialog.Type) as PluginConfigurationViewModel;
|
||||
if (viewModel == null)
|
||||
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
|
||||
|
||||
_window = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
|
||||
_window.Closed += (_, _) => _window = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("An exception occured while trying to show the plugin's settings window", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenPluginDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
Utilities.OpenFolder(Plugin.Directory.FullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteReload()
|
||||
{
|
||||
bool wasEnabled = IsEnabled;
|
||||
|
||||
await Task.Run(() => _pluginManagementService.UnloadPlugin(Plugin));
|
||||
bool wasEnabled = _plugin.IsEnabled;
|
||||
await Task.Run(() => _pluginManagementService.UnloadPlugin(_plugin));
|
||||
|
||||
PluginFeatures.Clear();
|
||||
|
||||
Plugin = _pluginManagementService.LoadPlugin(Plugin.Directory);
|
||||
foreach (PluginFeatureInfo pluginFeatureInfo in Plugin.Features)
|
||||
PluginFeatures.Add(_settingsVmFactory.CreatePluginFeatureViewModel(pluginFeatureInfo, false));
|
||||
_plugin = _pluginManagementService.LoadPlugin(_plugin.Directory);
|
||||
|
||||
PluginViewModel = _settingsVmFactory.PluginViewModel(_plugin, Reload);
|
||||
foreach (PluginFeatureInfo pluginFeatureInfo in _plugin.Features)
|
||||
PluginFeatures.Add(_settingsVmFactory.PluginFeatureViewModel(pluginFeatureInfo, false));
|
||||
|
||||
if (wasEnabled)
|
||||
await UpdateEnabled(true);
|
||||
await PluginViewModel.UpdateEnabled(true);
|
||||
|
||||
_notificationService.CreateNotification().WithTitle("Reloaded plugin.").Show();
|
||||
}
|
||||
|
||||
private async Task ExecuteInstallPrerequisites()
|
||||
{
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features.Where(f => f.AlwaysEnabled));
|
||||
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any()))
|
||||
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
||||
}
|
||||
|
||||
private async Task ExecuteRemovePrerequisites(bool forPluginRemoval = false)
|
||||
{
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(!forPluginRemoval ? Plugin.Features.Where(f => f.AlwaysEnabled) : Plugin.Features);
|
||||
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
||||
{
|
||||
await PluginPrerequisitesUninstallDialogViewModel.Show(_windowService, subjects, forPluginRemoval ? "Skip, remove plugin" : "Cancel");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteRemoveSettings()
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Clear plugin settings", "Are you sure you want to clear the settings of this plugin?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
bool wasEnabled = IsEnabled;
|
||||
|
||||
if (IsEnabled)
|
||||
await UpdateEnabled(false);
|
||||
|
||||
_pluginManagementService.RemovePluginSettings(Plugin);
|
||||
|
||||
if (wasEnabled)
|
||||
await UpdateEnabled(true);
|
||||
|
||||
_notificationService.CreateNotification().WithTitle("Cleared plugin settings.").Show();
|
||||
}
|
||||
|
||||
private async Task ExecuteRemove()
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Remove plugin", "Are you sure you want to remove this plugin?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
// If the plugin or any of its features has uninstall actions, offer to run these
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features);
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
||||
await ExecuteRemovePrerequisites(true);
|
||||
|
||||
try
|
||||
{
|
||||
_pluginManagementService.RemovePlugin(Plugin, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Failed to remove plugin", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
_notificationService.CreateNotification().WithTitle("Removed plugin.").Show();
|
||||
}
|
||||
|
||||
private void ExecuteShowLogsFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
Utilities.OpenFolder(Constants.LogsFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateEnabled(bool enable)
|
||||
{
|
||||
if (Enabling)
|
||||
return;
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Run(() => _pluginManagementService.DisablePlugin(Plugin, true));
|
||||
}
|
||||
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());
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Enabling = true;
|
||||
if (Plugin.Info.RequiresAdmin && !_coreService.IsElevated)
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Enable plugin", "This plugin requires admin rights, are you sure you want to enable it?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if all prerequisites are met async
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features.Where(f => f.AlwaysEnabled || f.EnabledInStorage));
|
||||
|
||||
if (subjects.Any(s => !s.ArePrerequisitesMet()))
|
||||
{
|
||||
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
||||
if (!subjects.All(s => s.ArePrerequisitesMet()))
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(() => _pluginManagementService.EnablePlugin(Plugin, true, true));
|
||||
}
|
||||
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());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabling = false;
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckPrerequisites()
|
||||
{
|
||||
CanInstallPrerequisites = Plugin.Info.PlatformPrerequisites.Any() ||
|
||||
Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any());
|
||||
CanRemovePrerequisites = Plugin.Info.PlatformPrerequisites.Any(p => p.UninstallActions.Any()) ||
|
||||
Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any(p => p.UninstallActions.Any()));
|
||||
}
|
||||
|
||||
private void OnPluginToggled(object? sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
if (!IsEnabled)
|
||||
_window?.Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<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:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Plugins.PluginView"
|
||||
x:DataType="plugins:PluginViewModel">
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*, Auto">
|
||||
<shared:ArtemisIcon Icon="{CompiledBinding Plugin.Info.ResolvedIcon}"
|
||||
Fill="False"
|
||||
Width="48"
|
||||
Height="48"
|
||||
Margin="0 5 0 0"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="3"
|
||||
VerticalAlignment="Top" />
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="0" Classes="h5 no-margin" Text="{CompiledBinding Plugin.Info.Name}" />
|
||||
|
||||
<ItemsControl Grid.Column="2" Grid.Row="0" IsVisible="{CompiledBinding Platforms.Count}" Items="{CompiledBinding Platforms}" HorizontalAlignment="Right">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="5" Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="1"
|
||||
Classes="subtitle"
|
||||
Text="{CompiledBinding Plugin.Info.Author}"
|
||||
IsVisible="{CompiledBinding Plugin.Info.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Grid.Row="2"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0 5"
|
||||
Text="{CompiledBinding Plugin.Info.Description}" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,Auto">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<controls:SplitButton Content="Settings" Command="{CompiledBinding OpenSettings}">
|
||||
<controls:SplitButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom" IsOpen="{CompiledBinding IsSettingsPopupOpen, Mode=OneWayToSource}">
|
||||
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="FolderOpen" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Reload plugin" Command="{CompiledBinding Reload}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Reload" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Install prerequisites" Command="{CompiledBinding InstallPrerequisites}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="CheckAll" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Remove prerequisites" Command="{CompiledBinding RemovePrerequisites}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Delete" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Clear plugin settings" Command="{CompiledBinding RemoveSettings}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="DatabaseRemove" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Remove plugin" Command="{CompiledBinding Remove}">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="DeleteForever" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</controls:SplitButton.Flyout>
|
||||
</controls:SplitButton>
|
||||
|
||||
<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}">
|
||||
<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}">
|
||||
<avalonia:MaterialIcon Kind="Git" />
|
||||
</controls:HyperlinkButton>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Name="EnabledToggle"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{CompiledBinding !Enabling}"
|
||||
IsChecked="{CompiledBinding IsEnabled, Mode=OneWay}"
|
||||
IsEnabled="{CompiledBinding Plugin.Info.IsCompatible}">
|
||||
<StackPanel x:Name="EnableText" Orientation="Horizontal">
|
||||
<TextBlock>Enable plugin</TextBlock>
|
||||
<avalonia:MaterialIcon Kind="ShieldHalfFull"
|
||||
Margin="5 0 0 0"
|
||||
ToolTip.Tip="Plugin requires admin rights"
|
||||
IsVisible="{CompiledBinding Plugin.Info.RequiresAdmin}" />
|
||||
</StackPanel>
|
||||
</CheckBox>
|
||||
|
||||
<ProgressBar Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{CompiledBinding Enabling}"
|
||||
IsIndeterminate="True" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.UI.Screens.Plugins;
|
||||
|
||||
public partial class PluginView : ReactiveUserControl<PluginViewModel>
|
||||
{
|
||||
private CheckBox _enabledToggle;
|
||||
|
||||
public PluginView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_enabledToggle = this.Find<CheckBox>("EnabledToggle");
|
||||
_enabledToggle.Click += EnabledToggleOnClick;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void EnabledToggleOnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => ViewModel?.UpdateEnabled(!ViewModel.Plugin.IsEnabled));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using Material.Icons;
|
||||
using Ninject;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Plugins;
|
||||
|
||||
public class PluginViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IWindowService _windowService;
|
||||
private bool _canInstallPrerequisites;
|
||||
private bool _canRemovePrerequisites;
|
||||
private bool _enabling;
|
||||
private bool _isSettingsPopupOpen;
|
||||
private Plugin _plugin;
|
||||
private Window? _window;
|
||||
|
||||
public PluginViewModel(Plugin plugin,
|
||||
ReactiveCommand<Unit, Unit>? reload,
|
||||
ICoreService coreService,
|
||||
IWindowService windowService,
|
||||
INotificationService notificationService,
|
||||
IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_plugin = plugin;
|
||||
_coreService = coreService;
|
||||
_windowService = windowService;
|
||||
_notificationService = notificationService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
Platforms = new ObservableCollection<PluginPlatformViewModel>();
|
||||
if (Plugin.Info.Platforms != null)
|
||||
{
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.Windows))
|
||||
Platforms.Add(new PluginPlatformViewModel("Windows", MaterialIconKind.MicrosoftWindows));
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.Linux))
|
||||
Platforms.Add(new PluginPlatformViewModel("Linux", MaterialIconKind.Linux));
|
||||
if (Plugin.Info.Platforms.Value.HasFlag(PluginPlatform.OSX))
|
||||
Platforms.Add(new PluginPlatformViewModel("OSX", MaterialIconKind.Apple));
|
||||
}
|
||||
|
||||
Reload = reload;
|
||||
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin.ConfigurationDialog != null));
|
||||
RemoveSettings = ReactiveCommand.CreateFromTask(ExecuteRemoveSettings);
|
||||
Remove = ReactiveCommand.CreateFromTask(ExecuteRemove);
|
||||
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
||||
RemovePrerequisites = ReactiveCommand.CreateFromTask<bool>(ExecuteRemovePrerequisites, this.WhenAnyValue(x => x.CanRemovePrerequisites));
|
||||
ShowLogsFolder = ReactiveCommand.Create(ExecuteShowLogsFolder);
|
||||
OpenPluginDirectory = ReactiveCommand.Create(ExecuteOpenPluginDirectory);
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
Plugin.Enabled += OnPluginToggled;
|
||||
Plugin.Disabled += OnPluginToggled;
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
Plugin.Enabled -= OnPluginToggled;
|
||||
Plugin.Disabled -= OnPluginToggled;
|
||||
_window?.Close();
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit>? Reload { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> RemoveSettings { get; }
|
||||
public ReactiveCommand<Unit, Unit> Remove { get; }
|
||||
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
||||
public ReactiveCommand<bool, Unit> RemovePrerequisites { get; }
|
||||
public ReactiveCommand<Unit, Unit> ShowLogsFolder { get; }
|
||||
public ReactiveCommand<Unit, Unit> OpenPluginDirectory { get; }
|
||||
|
||||
public ObservableCollection<PluginPlatformViewModel> Platforms { get; }
|
||||
|
||||
public Plugin Plugin
|
||||
{
|
||||
get => _plugin;
|
||||
set => RaiseAndSetIfChanged(ref _plugin, value);
|
||||
}
|
||||
|
||||
public bool Enabling
|
||||
{
|
||||
get => _enabling;
|
||||
set => RaiseAndSetIfChanged(ref _enabling, value);
|
||||
}
|
||||
|
||||
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
||||
public bool IsEnabled => Plugin.IsEnabled;
|
||||
|
||||
public bool IsSettingsPopupOpen
|
||||
{
|
||||
get => _isSettingsPopupOpen;
|
||||
set
|
||||
{
|
||||
if (!RaiseAndSetIfChanged(ref _isSettingsPopupOpen, value)) return;
|
||||
CheckPrerequisites();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanInstallPrerequisites
|
||||
{
|
||||
get => _canInstallPrerequisites;
|
||||
set => RaiseAndSetIfChanged(ref _canInstallPrerequisites, value);
|
||||
}
|
||||
|
||||
public bool CanRemovePrerequisites
|
||||
{
|
||||
get => _canRemovePrerequisites;
|
||||
set => RaiseAndSetIfChanged(ref _canRemovePrerequisites, value);
|
||||
}
|
||||
|
||||
private void ExecuteOpenSettings()
|
||||
{
|
||||
if (Plugin.ConfigurationDialog == null)
|
||||
return;
|
||||
|
||||
if (_window != null)
|
||||
{
|
||||
_window.WindowState = WindowState.Normal;
|
||||
_window.Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
PluginConfigurationViewModel? viewModel = Plugin.Kernel!.Get(Plugin.ConfigurationDialog.Type) as PluginConfigurationViewModel;
|
||||
if (viewModel == null)
|
||||
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
|
||||
|
||||
_window = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
|
||||
_window.Closed += (_, _) => _window = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("An exception occured while trying to show the plugin's settings window", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteOpenPluginDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
Utilities.OpenFolder(Plugin.Directory.FullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteInstallPrerequisites()
|
||||
{
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features.Where(f => f.AlwaysEnabled));
|
||||
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any()))
|
||||
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
||||
}
|
||||
|
||||
private async Task ExecuteRemovePrerequisites(bool forPluginRemoval = false)
|
||||
{
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(!forPluginRemoval ? Plugin.Features.Where(f => f.AlwaysEnabled) : Plugin.Features);
|
||||
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
||||
{
|
||||
await PluginPrerequisitesUninstallDialogViewModel.Show(_windowService, subjects, forPluginRemoval ? "Skip, remove plugin" : "Cancel");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteRemoveSettings()
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Clear plugin settings", "Are you sure you want to clear the settings of this plugin?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
bool wasEnabled = IsEnabled;
|
||||
|
||||
if (IsEnabled)
|
||||
await UpdateEnabled(false);
|
||||
|
||||
_pluginManagementService.RemovePluginSettings(Plugin);
|
||||
|
||||
if (wasEnabled)
|
||||
await UpdateEnabled(true);
|
||||
|
||||
_notificationService.CreateNotification().WithTitle("Cleared plugin settings.").Show();
|
||||
}
|
||||
|
||||
private async Task ExecuteRemove()
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Remove plugin", "Are you sure you want to remove this plugin?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
// If the plugin or any of its features has uninstall actions, offer to run these
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features);
|
||||
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
||||
await ExecuteRemovePrerequisites(true);
|
||||
|
||||
try
|
||||
{
|
||||
_pluginManagementService.RemovePlugin(Plugin, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Failed to remove plugin", e);
|
||||
throw;
|
||||
}
|
||||
|
||||
_notificationService.CreateNotification().WithTitle("Removed plugin.").Show();
|
||||
}
|
||||
|
||||
private void ExecuteShowLogsFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
Utilities.OpenFolder(Constants.LogsFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateEnabled(bool enable)
|
||||
{
|
||||
if (Enabling)
|
||||
return;
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Run(() => _pluginManagementService.DisablePlugin(Plugin, true));
|
||||
}
|
||||
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());
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Enabling = true;
|
||||
if (Plugin.Info.RequiresAdmin && !_coreService.IsElevated)
|
||||
{
|
||||
bool confirmed = await _windowService.ShowConfirmContentDialog("Enable plugin", "This plugin requires admin rights, are you sure you want to enable it?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if all prerequisites are met async
|
||||
List<IPrerequisitesSubject> subjects = new() {Plugin.Info};
|
||||
subjects.AddRange(Plugin.Features.Where(f => f.AlwaysEnabled || f.EnabledInStorage));
|
||||
|
||||
if (subjects.Any(s => !s.ArePrerequisitesMet()))
|
||||
{
|
||||
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
||||
if (!subjects.All(s => s.ArePrerequisitesMet()))
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Run(() => _pluginManagementService.EnablePlugin(Plugin, true, true));
|
||||
}
|
||||
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());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabling = false;
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckPrerequisites()
|
||||
{
|
||||
CanInstallPrerequisites = Plugin.Info.PlatformPrerequisites.Any() ||
|
||||
Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any());
|
||||
CanRemovePrerequisites = Plugin.Info.PlatformPrerequisites.Any(p => p.UninstallActions.Any()) ||
|
||||
Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any(p => p.UninstallActions.Any()));
|
||||
}
|
||||
|
||||
private void OnPluginToggled(object? sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||
if (!IsEnabled)
|
||||
_window?.Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user