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

Plugins - Fixed GetFeature<T> always returning null

Plugins - Added AlwaysEnabled property to [PluginFeature] attribute
This commit is contained in:
Robert 2021-03-26 19:39:48 +01:00
parent 0a7c724de0
commit 5545bdb783
7 changed files with 72 additions and 19 deletions

View File

@ -107,7 +107,7 @@ namespace Artemis.Core
/// <returns>If found, the instance of the feature</returns>
public T? GetFeature<T>() where T : PluginFeature
{
return _features.FirstOrDefault(i => i.Instance is T) as T;
return _features.FirstOrDefault(i => i.Instance is T)?.Instance as T;
}
/// <inheritdoc />
@ -164,6 +164,11 @@ namespace Artemis.Core
}
}
internal bool HasEnabledFeatures()
{
return Entity.Features.Any(f => f.IsEnabled) || Features.Any(f => f.AlwaysEnabled);
}
#region IDisposable
/// <summary>

View File

@ -23,5 +23,10 @@ namespace Artemis.Core
/// available icons
/// </summary>
public string? Icon { get; set; }
/// <summary>
/// Marks the feature to always be enabled as long as the plugin is enabled
/// </summary>
public bool AlwaysEnabled { get; set; }
}
}
}

View File

@ -28,7 +28,8 @@ namespace Artemis.Core
Name = attribute?.Name ?? featureType.Name.Humanize(LetterCasing.Title);
Description = attribute?.Description;
Icon = attribute?.Icon;
AlwaysEnabled = attribute?.AlwaysEnabled ?? false;
if (Icon != null) return;
if (typeof(BaseDataModelExpansion).IsAssignableFrom(featureType))
Icon = "TableAdd";
@ -55,6 +56,7 @@ namespace Artemis.Core
Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title);
Description = attribute?.Description;
Icon = attribute?.Icon;
AlwaysEnabled = attribute?.AlwaysEnabled ?? false;
Instance = instance;
if (Icon != null) return;
@ -111,6 +113,12 @@ namespace Artemis.Core
set => SetAndNotify(ref _icon, value);
}
/// <summary>
/// Marks the feature to always be enabled as long as the plugin is enabled and cannot be disabled
/// </summary>
[JsonProperty]
public bool AlwaysEnabled { get; }
/// <summary>
/// Gets the feature this info is associated with
/// </summary>

View File

@ -207,7 +207,7 @@ namespace Artemis.Core.Services
// ReSharper disable InconsistentlySynchronizedField - It's read-only, idc
_logger.Debug("Loaded {count} plugin(s)", _plugins.Count);
bool adminRequired = _plugins.Any(p => p.Info.RequiresAdmin && p.Entity.IsEnabled && p.Entity.Features.Any(f => f.IsEnabled));
bool adminRequired = _plugins.Any(p => p.Info.RequiresAdmin && p.Entity.IsEnabled && p.HasEnabledFeatures());
if (!isElevated && adminRequired)
{
_logger.Information("Restarting because one or more plugins requires elevation");
@ -340,7 +340,7 @@ namespace Artemis.Core.Services
if (plugin.Assembly == null)
throw new ArtemisPluginException(plugin, "Cannot enable a plugin that hasn't successfully been loaded");
if (plugin.Info.RequiresAdmin && plugin.Entity.Features.Any(f => f.IsEnabled) && !_isElevated)
if (plugin.Info.RequiresAdmin && plugin.HasEnabledFeatures() && !_isElevated)
{
if (!saveState)
throw new ArtemisCoreException("Cannot enable a plugin that requires elevation without saving it's state.");
@ -387,7 +387,7 @@ namespace Artemis.Core.Services
}
// Activate features after they are all loaded
foreach (PluginFeatureInfo pluginFeature in plugin.Features.Where(f => f.Instance != null && f.Instance.Entity.IsEnabled))
foreach (PluginFeatureInfo pluginFeature in plugin.Features.Where(f => f.Instance != null && (f.Instance.Entity.IsEnabled || f.AlwaysEnabled)))
{
try
{

View File

@ -50,13 +50,17 @@
VerticalAlignment="Center"
Margin="8"
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay, FallbackValue=Collapsed}"
Orientation="Horizontal">
Orientation="Horizontal"
ToolTip="This feature cannot be disabled without disabling the whole plugin"
ToolTipService.IsEnabled="{Binding FeatureInfo.AlwaysEnabled}">
<materialDesign:PackIcon Kind="ShieldHalfFull"
ToolTip="Plugin requires admin rights"
VerticalAlignment="Center"
Margin="0 0 5 0"
Visibility="{Binding ShowShield, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding IsEnabled}" IsEnabled="{Binding FeatureInfo.Plugin.IsEnabled}">
<CheckBox Style="{StaticResource MaterialDesignCheckBox}"
IsChecked="{Binding IsEnabled}"
IsEnabled="{Binding CanToggleEnabled}">
Feature enabled
</CheckBox>
</StackPanel>

View File

@ -16,6 +16,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
private readonly IPluginManagementService _pluginManagementService;
private bool _enabling;
private readonly IMessageService _messageService;
private bool _canToggleEnabled;
public PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo,
bool showShield,
@ -50,6 +51,8 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
set => Task.Run(() => UpdateEnabled(value));
}
public bool CanToggleEnabled => FeatureInfo.Plugin.IsEnabled && !FeatureInfo.AlwaysEnabled;
public void ShowLogsFolder()
{
try
@ -76,6 +79,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
_pluginManagementService.PluginFeatureEnabled += OnFeatureEnableStopped;
_pluginManagementService.PluginFeatureEnableFailed += OnFeatureEnableStopped;
FeatureInfo.Plugin.Enabled += PluginOnToggled;
FeatureInfo.Plugin.Disabled += PluginOnToggled;
base.OnInitialActivate();
}
@ -85,6 +91,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
_pluginManagementService.PluginFeatureEnabled -= OnFeatureEnableStopped;
_pluginManagementService.PluginFeatureEnableFailed -= OnFeatureEnableStopped;
FeatureInfo.Plugin.Enabled -= PluginOnToggled;
FeatureInfo.Plugin.Disabled -= PluginOnToggled;
base.OnClose();
}
@ -147,6 +156,11 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
NotifyOfPropertyChange(nameof(LoadException));
}
private void PluginOnToggled(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(CanToggleEnabled));
}
#endregion
}
}

View File

@ -1,6 +1,9 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeEditing/GenerateMemberBody/DocumentationGenerationKind/@EntryValue">Inherit</s:String>
<s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/WrapIntoRegions/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeObjectCreationWhenTypeNotEvident/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuspiciousTypeConversion_002EGlobal/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Built-in: Full Cleanup</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/APPLY_ON_COMPLETION/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
@ -128,17 +131,6 @@
&lt;Name /&gt;&#xD;
&lt;/Entry.SortBy&gt;&#xD;
&lt;/Entry&gt;&#xD;
&lt;Entry Priority="100" DisplayName="Public Enums"&gt;&#xD;
&lt;Entry.Match&gt;&#xD;
&lt;And&gt;&#xD;
&lt;Access Is="Public" /&gt;&#xD;
&lt;Kind Is="Enum" /&gt;&#xD;
&lt;/And&gt;&#xD;
&lt;/Entry.Match&gt;&#xD;
&lt;Entry.SortBy&gt;&#xD;
&lt;Name /&gt;&#xD;
&lt;/Entry.SortBy&gt;&#xD;
&lt;/Entry&gt;&#xD;
&lt;Entry DisplayName="Static Fields and Constants"&gt;&#xD;
&lt;Entry.Match&gt;&#xD;
&lt;Or&gt;&#xD;
@ -207,16 +199,41 @@
&lt;ImplementsInterface Immediate="True" /&gt;&#xD;
&lt;/Entry.SortBy&gt;&#xD;
&lt;/Entry&gt;&#xD;
&lt;Entry Priority="100" DisplayName="Public Enums"&gt;&#xD;
&lt;Entry.Match&gt;&#xD;
&lt;And&gt;&#xD;
&lt;Access Is="Public" /&gt;&#xD;
&lt;Kind Is="Enum" /&gt;&#xD;
&lt;/And&gt;&#xD;
&lt;/Entry.Match&gt;&#xD;
&lt;Entry.SortBy&gt;&#xD;
&lt;Name /&gt;&#xD;
&lt;/Entry.SortBy&gt;&#xD;
&lt;/Entry&gt;&#xD;
&lt;Region Name="Events" /&gt;&#xD;
&lt;Region Name="Event handlers" /&gt;&#xD;
&lt;Region Name="IDisposable"&gt;&#xD;
&lt;Region.GroupBy&gt;&#xD;
&lt;ImplementsInterface /&gt;&#xD;
&lt;/Region.GroupBy&gt;&#xD;
&lt;/Region&gt;&#xD;
&lt;/TypePattern&gt;&#xD;
&lt;/Patterns&gt;</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">ERROR</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=DisposePattern/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=DisposePattern/Options/=ChangeDispose/@EntryIndexedValue">Replace</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Formatting/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Formatting/Options/=UseNameOf/@EntryIndexedValue">True</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">True</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SK/@EntryIndexedValue">SK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>