1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Plugins - Don't dispose Plugin when disabling after it has been injected into a feature

This commit is contained in:
Robert 2022-07-22 23:25:35 +02:00
parent 75d85985a9
commit 289a411545
9 changed files with 58 additions and 33 deletions

View File

@ -22,7 +22,7 @@ namespace Artemis.Core.Ninject
Kernel.Components.Remove<IMissingBindingResolver, SelfBindingResolver>();
Kernel.Bind<Plugin>().ToConstant(Plugin);
Kernel.Bind<Plugin>().ToConstant(Plugin).InTransientScope();
// Bind plugin service interfaces
Kernel.Bind(x =>

View File

@ -97,7 +97,7 @@ namespace Artemis.UI.Shared
/// Occurs when a LED of the device has been clicked
/// </summary>
public event EventHandler<LedClickedEventArgs>? LedClicked;
/// <summary>
/// Occurs when the device was clicked but not on a LED.
/// </summary>
@ -259,8 +259,6 @@ namespace Artemis.UI.Shared
private void SetupForDevice()
{
_deviceImage?.Dispose();
_deviceImage = null;
_highlightedLeds = new List<DeviceVisualizerLed>();
_dimmedLeds = new List<DeviceVisualizerLed>();
@ -296,7 +294,11 @@ namespace Artemis.UI.Shared
Task.Run(() =>
{
if (device.Layout?.Image == null || !File.Exists(device.Layout.Image.LocalPath))
{
_deviceImage?.Dispose();
_deviceImage = null;
return;
}
try
{
@ -312,6 +314,7 @@ namespace Artemis.UI.Shared
deviceVisualizerLed.DrawBitmap(context);
}
_deviceImage?.Dispose();
_deviceImage = renderTargetBitmap;
Dispatcher.UIThread.Post(InvalidateMeasure);
@ -337,7 +340,5 @@ namespace Artemis.UI.Shared
}
#endregion
}
}

View File

@ -44,6 +44,10 @@
<ToggleButton Classes="icon-button">
<avalonia:MaterialIcon Kind="BlockChain" />
</ToggleButton>
<Button Classes="icon-button">
<avalonia:MaterialIcon Kind="Cog" />
</Button>
</StackPanel>
</Border>
</Design.PreviewWith>

View File

@ -35,19 +35,10 @@
IsHitTestVisible="False">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type plugins: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" />
</Border>
<Border Grid.Row="0" Grid.Column="0" Classes="status-border" IsVisible="{CompiledBinding IsMet}" Background="#32a852">
<avalonia:MaterialIcon Kind="Check" />
</Border>
<StackPanel Margin="8 0 0 0" Grid.Column="1" VerticalAlignment="Stretch">
<TextBlock FontWeight="Bold" Text="{CompiledBinding PluginPrerequisite.Name}" TextWrapping="Wrap" />
<TextBlock Text="{CompiledBinding PluginPrerequisite.Description}" TextWrapping="Wrap" />
</StackPanel>
</Grid>
<StackPanel Margin="0 6" VerticalAlignment="Stretch">
<TextBlock FontWeight="Bold" Text="{CompiledBinding PluginPrerequisite.Name}" TextWrapping="Wrap" />
<TextBlock Text="{CompiledBinding PluginPrerequisite.Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

View File

@ -88,7 +88,8 @@ namespace Artemis.UI.Screens.Plugins
// Disable all subjects that are features if still required
foreach (IPrerequisitesSubject prerequisitesSubject in _subjects)
{
if (prerequisitesSubject is not PluginFeatureInfo featureInfo) continue;
if (prerequisitesSubject is not PluginFeatureInfo featureInfo)
continue;
// Disable the parent plugin if the feature is AlwaysEnabled
if (featureInfo.AlwaysEnabled)

View File

@ -11,12 +11,12 @@
<Grid ColumnDefinitions="30,*,Auto">
<Grid.ContextFlyout>
<MenuFlyout>
<MenuItem Header="Install prerequisites" Command="{Binding InstallPrerequisites}">
<MenuItem Header="Install prerequisites" Command="{CompiledBinding InstallPrerequisites}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="CheckAll" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Remove prerequisites" Command="{Binding RemovePrerequisites}">
<MenuItem Header="Remove prerequisites" Command="{CompiledBinding RemovePrerequisites}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Delete" />
</MenuItem.Icon>
@ -58,12 +58,30 @@
ToolTip.Tip="Plugin requires admin rights"
VerticalAlignment="Center"
Margin="0 0 5 0"
IsVisible="{Binding ShowShield}" />
IsVisible="{CompiledBinding ShowShield}" />
<CheckBox IsChecked="{CompiledBinding IsEnabled}" IsEnabled="{CompiledBinding CanToggleEnabled}">
Enable feature
</CheckBox>
<Button Classes="icon-button" Margin="5 0 0 0" IsVisible="{CompiledBinding CanInstallPrerequisites}">
<Button.Flyout>
<MenuFlyout Placement="Bottom" >
<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>
</MenuFlyout>
</Button.Flyout>
<avalonia:MaterialIcon Kind="DotsVertical"></avalonia:MaterialIcon>
</Button>
</StackPanel>
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="7" IsVisible="{CompiledBinding Enabling}">
<ProgressBar Value="0" IsIndeterminate="True" />

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Artemis.Core;
@ -37,6 +38,11 @@ namespace Artemis.UI.Screens.Plugins
FeatureInfo = pluginFeatureInfo;
ShowShield = FeatureInfo.Plugin.Info.RequiresAdmin && showShield;
ShowLogsFolder = ReactiveCommand.Create(ExecuteShowLogsFolder);
ViewLoadException = ReactiveCommand.Create(ExecuteViewLoadException);
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites);
RemovePrerequisites = ReactiveCommand.CreateFromTask(ExecuteRemovePrerequisites);
this.WhenActivated(d =>
{
_pluginManagementService.PluginFeatureEnabling += OnFeatureEnabling;
@ -58,6 +64,11 @@ namespace Artemis.UI.Screens.Plugins
});
}
public ReactiveCommand<Unit, Unit> ShowLogsFolder { get; }
public ReactiveCommand<Unit, Unit> ViewLoadException { get; }
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
public ReactiveCommand<Unit, Unit> RemovePrerequisites { get; }
public PluginFeatureInfo FeatureInfo { get; }
public Exception? LoadException => FeatureInfo.LoadException;
@ -80,7 +91,7 @@ namespace Artemis.UI.Screens.Plugins
public bool CanRemovePrerequisites => FeatureInfo.PlatformPrerequisites.Any(p => p.UninstallActions.Any());
public bool IsPopupEnabled => CanInstallPrerequisites || CanRemovePrerequisites;
public void ShowLogsFolder()
private void ExecuteShowLogsFolder()
{
try
{
@ -92,19 +103,19 @@ namespace Artemis.UI.Screens.Plugins
}
}
public void ViewLoadException()
private void ExecuteViewLoadException()
{
if (LoadException != null)
_windowService.ShowExceptionDialog("Feature failed to enable", LoadException);
}
public async Task InstallPrerequisites()
private async Task ExecuteInstallPrerequisites()
{
if (FeatureInfo.PlatformPrerequisites.Any())
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, new List<IPrerequisitesSubject> {FeatureInfo});
}
public async Task RemovePrerequisites()
private async Task ExecuteRemovePrerequisites()
{
if (FeatureInfo.PlatformPrerequisites.Any(p => p.UninstallActions.Any()))
{
@ -126,7 +137,7 @@ namespace Artemis.UI.Screens.Plugins
this.RaisePropertyChanged(nameof(IsEnabled));
_notificationService.CreateNotification()
.WithMessage($"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.")
.HavingButton(b => b.WithText("View logs").WithAction(ShowLogsFolder))
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.WithSeverity(NotificationSeverity.Error)
.Show();
return;
@ -165,7 +176,7 @@ namespace Artemis.UI.Screens.Plugins
{
_notificationService.CreateNotification()
.WithMessage($"Failed to enable '{FeatureInfo.Name}'.\r\n{e.Message}")
.HavingButton(b => b.WithText("View logs").WithAction(ShowLogsFolder))
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
.WithSeverity(NotificationSeverity.Error)
.Show();
}

View File

@ -31,9 +31,8 @@ namespace Artemis.UI.Screens.Plugins
? PluginPrerequisite.InstallActions.Select(a => new PluginPrerequisiteActionViewModel(a))
: PluginPrerequisite.UninstallActions.Select(a => new PluginPrerequisiteActionViewModel(a)));
this.WhenAnyValue(x => x.Installing, x => x.Uninstalling, (i, u) => i || u).ToProperty(this, x => x.Busy, out _busy);
this.WhenAnyValue(x => x.ActiveAction, a => Actions.IndexOf(a!)).ToProperty(this, x => x.ActiveStepNumber, out _activeStepNumber);
_busy = this.WhenAnyValue(x => x.Installing, x => x.Uninstalling, (i, u) => i || u).ToProperty(this, x => x.Busy);
_activeStepNumber = this.WhenAnyValue(x => x.ActiveAction, a => Actions.IndexOf(a!) + 1).ToProperty(this, x => x.ActiveStepNumber);
this.WhenActivated(d =>
{

View File

@ -16,7 +16,7 @@
<Button Grid.Row="0" Grid.Column="1" Classes="accent" Command="{CompiledBinding ImportPlugin}" HorizontalAlignment="Right">Import plugin</Button>
</Grid>
<ScrollViewer Grid.Row="1" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ScrollViewer Grid.Row="1" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
<ItemsControl Items="{CompiledBinding Plugins}" MaxWidth="900" VerticalAlignment="Center"/>
</ScrollViewer>
</Grid>