diff --git a/ci/azure-pipelines.yml b/ci/azure-pipelines.yml
index 2f40282d0..8e16ec412 100644
--- a/ci/azure-pipelines.yml
+++ b/ci/azure-pipelines.yml
@@ -53,7 +53,7 @@ steps:
command: 'publish'
publishWebProjects: false
projects: '$(artemisSolution)'
- arguments: '--runtime win-x64 --self-contained false --output $(Build.ArtifactStagingDirectory)/build /nowarn:cs1591'
+ arguments: '--runtime win-x64 --self-contained false --configuration Release --output $(Build.ArtifactStagingDirectory)/build /nowarn:cs1591'
zipAfterPublish: false
modifyOutputPath: false
@@ -73,12 +73,13 @@ steps:
fileType: 'json'
targetFiles: '**/buildinfo.json'
+# Copy Artemis binaries to where plugin projects expect them
- task: CopyFiles@2
displayName: 'Plugins - Prepare Artemis binaries'
inputs:
SourceFolder: '$(Build.ArtifactStagingDirectory)/build'
Contents: '**'
- TargetFolder: 'Artemis/src/Artemis.UI/bin/x64/Debug/net5.0-windows'
+ TargetFolder: 'Artemis/src/Artemis.UI/bin/net5.0-windows'
- task: PowerShell@2
displayName: 'Plugins - Insert build number into plugin.json'
@@ -99,7 +100,7 @@ steps:
inputs:
command: 'publish'
publishWebProjects: false
- arguments: '--runtime win-x64 --self-contained false --output $(Build.ArtifactStagingDirectory)/build/Plugins'
+ arguments: '--runtime win-x64 --configuration Release --self-contained false --output $(Build.ArtifactStagingDirectory)/build/Plugins'
projects: '$(pluginProjects)'
zipAfterPublish: true
diff --git a/src/Artemis.Core/Ninject/CoreModule.cs b/src/Artemis.Core/Ninject/CoreModule.cs
index 5408951de..b3dee7af1 100644
--- a/src/Artemis.Core/Ninject/CoreModule.cs
+++ b/src/Artemis.Core/Ninject/CoreModule.cs
@@ -1,4 +1,7 @@
-using System.IO;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
using Artemis.Core.Services;
using Artemis.Storage;
using Artemis.Storage.Migrations.Interfaces;
diff --git a/src/Artemis.Core/Ninject/LoggerProvider.cs b/src/Artemis.Core/Ninject/LoggerProvider.cs
index fe2aaf5b6..713d8d835 100644
--- a/src/Artemis.Core/Ninject/LoggerProvider.cs
+++ b/src/Artemis.Core/Ninject/LoggerProvider.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using Ninject.Activation;
using Serilog;
using Serilog.Core;
diff --git a/src/Artemis.Core/Plugins/Plugin.cs b/src/Artemis.Core/Plugins/Plugin.cs
index 0b4379a09..da4e3f7aa 100644
--- a/src/Artemis.Core/Plugins/Plugin.cs
+++ b/src/Artemis.Core/Plugins/Plugin.cs
@@ -88,6 +88,11 @@ namespace Artemis.Core
///
internal PluginEntity Entity { get; set; }
+ ///
+ /// Populated when plugin settings are first loaded
+ ///
+ internal PluginSettings? Settings { get; set; }
+
///
/// Resolves the relative path provided in the parameter to an absolute path
///
@@ -101,7 +106,6 @@ namespace Artemis.Core
///
/// Looks up the instance of the feature of type
- /// Note: This method only returns instances of enabled features
///
/// The type of feature to find
/// If found, the instance of the feature
@@ -116,6 +120,83 @@ namespace Artemis.Core
return Info.ToString();
}
+ ///
+ /// Occurs when the plugin is enabled
+ ///
+ public event EventHandler? Enabled;
+
+ ///
+ /// Occurs when the plugin is disabled
+ ///
+ public event EventHandler? Disabled;
+
+ ///
+ /// Occurs when an feature is loaded and added to the plugin
+ ///
+ public event EventHandler? FeatureAdded;
+
+ ///
+ /// Occurs when an feature is disabled and removed from the plugin
+ ///
+ public event EventHandler? FeatureRemoved;
+
+ ///
+ /// Releases the unmanaged resources used by the object and optionally releases the managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources;
+ /// to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ foreach (PluginFeatureInfo feature in Features)
+ feature.Instance?.Dispose();
+ SetEnabled(false);
+
+ Kernel?.Dispose();
+ PluginLoader?.Dispose();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ _features.Clear();
+ }
+ }
+
+ ///
+ /// Invokes the Enabled event
+ ///
+ protected virtual void OnEnabled()
+ {
+ Enabled?.Invoke(this, EventArgs.Empty);
+ }
+
+ ///
+ /// Invokes the Disabled event
+ ///
+ protected virtual void OnDisabled()
+ {
+ Disabled?.Invoke(this, EventArgs.Empty);
+ }
+
+ ///
+ /// Invokes the FeatureAdded event
+ ///
+ protected virtual void OnFeatureAdded(PluginFeatureInfoEventArgs e)
+ {
+ FeatureAdded?.Invoke(this, e);
+ }
+
+ ///
+ /// Invokes the FeatureRemoved event
+ ///
+ protected virtual void OnFeatureRemoved(PluginFeatureInfoEventArgs e)
+ {
+ FeatureRemoved?.Invoke(this, e);
+ }
+
internal void ApplyToEntity()
{
Entity.Id = Guid;
@@ -169,96 +250,11 @@ namespace Artemis.Core
return Entity.Features.Any(f => f.IsEnabled) || Features.Any(f => f.AlwaysEnabled);
}
- #region IDisposable
-
- ///
- /// Releases the unmanaged resources used by the object and optionally releases the managed resources.
- ///
- ///
- /// to release both managed and unmanaged resources;
- /// to release only unmanaged resources.
- ///
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- foreach (PluginFeatureInfo feature in Features)
- feature.Instance?.Dispose();
- SetEnabled(false);
-
- Kernel?.Dispose();
- PluginLoader?.Dispose();
-
- GC.Collect();
- GC.WaitForPendingFinalizers();
-
- _features.Clear();
- }
- }
-
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
-
- #endregion
-
- #region Events
-
- ///
- /// Occurs when the plugin is enabled
- ///
- public event EventHandler? Enabled;
-
- ///
- /// Occurs when the plugin is disabled
- ///
- public event EventHandler? Disabled;
-
- ///
- /// Occurs when an feature is loaded and added to the plugin
- ///
- public event EventHandler? FeatureAdded;
-
- ///
- /// Occurs when an feature is disabled and removed from the plugin
- ///
- public event EventHandler? FeatureRemoved;
-
- ///
- /// Invokes the Enabled event
- ///
- protected virtual void OnEnabled()
- {
- Enabled?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- /// Invokes the Disabled event
- ///
- protected virtual void OnDisabled()
- {
- Disabled?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- /// Invokes the FeatureAdded event
- ///
- protected virtual void OnFeatureAdded(PluginFeatureInfoEventArgs e)
- {
- FeatureAdded?.Invoke(this, e);
- }
-
- ///
- /// Invokes the FeatureRemoved event
- ///
- protected virtual void OnFeatureRemoved(PluginFeatureInfoEventArgs e)
- {
- FeatureRemoved?.Invoke(this, e);
- }
-
- #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
index 03ee46316..1c34b58d2 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
@@ -17,6 +17,8 @@ namespace Artemis.Core
internal PluginSettings(Plugin plugin, IPluginRepository pluginRepository)
{
Plugin = plugin;
+ Plugin.Settings = this;
+
_pluginRepository = pluginRepository;
_settingEntities = new Dictionary();
}
@@ -65,5 +67,10 @@ namespace Artemis.Core
return pluginSetting;
}
}
+
+ internal void ClearSettings()
+ {
+ _settingEntities.Clear();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
index 7643c93ae..3791ae838 100644
--- a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
@@ -74,7 +74,14 @@ namespace Artemis.Core.Services
/// Unloads and permanently removes the provided plugin
///
/// The plugin to remove
- void RemovePlugin(Plugin plugin);
+ ///
+ void RemovePlugin(Plugin plugin, bool removeSettings);
+
+ ///
+ /// Removes the settings of a disabled plugin
+ ///
+ /// The plugin whose settings to remove
+ void RemovePluginSettings(Plugin plugin);
///
/// Enables the provided plugin feature
@@ -134,8 +141,6 @@ namespace Artemis.Core.Services
/// The action to take
void QueuePluginAction(Plugin plugin, PluginManagementAction pluginAction);
- #region Events
-
///
/// Occurs when built-in plugins are being loaded
///
@@ -190,7 +195,5 @@ namespace Artemis.Core.Services
/// Occurs when a plugin feature has been disabled
///
public event EventHandler PluginFeatureDisabled;
-
- #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 7840660ac..e0c16e1e2 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -479,7 +479,7 @@ namespace Artemis.Core.Services
if (existing != null)
try
{
- RemovePlugin(existing);
+ RemovePlugin(existing, false);
}
catch (Exception e)
{
@@ -519,7 +519,7 @@ namespace Artemis.Core.Services
return LoadPlugin(directoryInfo);
}
- public void RemovePlugin(Plugin plugin)
+ public void RemovePlugin(Plugin plugin, bool removeSettings)
{
DirectoryInfo directory = plugin.Directory;
lock (_plugins)
@@ -529,6 +529,16 @@ namespace Artemis.Core.Services
}
directory.Delete(true);
+ if (removeSettings)
+ RemovePluginSettings(plugin);
+ }
+
+ public void RemovePluginSettings(Plugin plugin)
+ {
+ if (plugin.IsEnabled)
+ throw new ArtemisCoreException("Cannot remove the settings of an enabled plugin");
+ _pluginRepository.RemoveSettings(plugin.Guid);
+ plugin.Settings?.ClearSettings();
}
#endregion
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
index d93ba4628..602eb2572 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
@@ -14,7 +14,8 @@ namespace Artemis.Storage.Repositories.Interfaces
PluginSettingEntity GetSettingByGuid(Guid pluginGuid);
PluginSettingEntity GetSettingByNameAndGuid(string name, Guid pluginGuid);
void SaveSetting(PluginSettingEntity pluginSettingEntity);
-
+ void RemoveSettings(Guid pluginGuid);
+
void AddQueuedAction(PluginQueuedActionEntity pluginQueuedActionEntity);
List GetQueuedActions();
List GetQueuedActions(Guid pluginGuid);
diff --git a/src/Artemis.Storage/Repositories/PluginRepository.cs b/src/Artemis.Storage/Repositories/PluginRepository.cs
index 5a923a60a..db67f0c91 100644
--- a/src/Artemis.Storage/Repositories/PluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/PluginRepository.cs
@@ -54,6 +54,12 @@ namespace Artemis.Storage.Repositories
_repository.Upsert(pluginSettingEntity);
}
+ ///
+ public void RemoveSettings(Guid pluginGuid)
+ {
+ _repository.DeleteMany(s => s.PluginGuid == pluginGuid);
+ }
+
public List GetQueuedActions()
{
return _repository.Query().ToList();
diff --git a/src/Artemis.UI/ApplicationStateManager.cs b/src/Artemis.UI/ApplicationStateManager.cs
index d07a0aa17..e2f1100a8 100644
--- a/src/Artemis.UI/ApplicationStateManager.cs
+++ b/src/Artemis.UI/ApplicationStateManager.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using System.Windows;
using Artemis.Core;
using Artemis.UI.Utilities;
+using Ninject;
using Stylet;
namespace Artemis.UI
@@ -19,13 +20,16 @@ namespace Artemis.UI
// ReSharper disable once NotAccessedField.Local - Kept in scope to ensure it does not get released
private Mutex _artemisMutex;
- public ApplicationStateManager(string[] startupArguments)
+ public ApplicationStateManager(IKernel kernel, string[] startupArguments)
{
StartupArguments = startupArguments;
IsElevated = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
Core.Utilities.RestartRequested += UtilitiesOnRestartRequested;
+
+ // On Windows shutdown dispose the kernel just so device providers get a chance to clean up
+ Application.Current.SessionEnding += (_, _) => kernel.Dispose();
}
public string[] StartupArguments { get; }
diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs
index 888851231..471d56412 100644
--- a/src/Artemis.UI/Bootstrapper.cs
+++ b/src/Artemis.UI/Bootstrapper.cs
@@ -6,7 +6,6 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Threading;
-using Artemis.Core;
using Artemis.Core.Ninject;
using Artemis.Core.Services;
using Artemis.UI.Ninject;
@@ -14,11 +13,9 @@ using Artemis.UI.Screens;
using Artemis.UI.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
-using Artemis.UI.SkiaSharp;
using Artemis.UI.Stylet;
using Ninject;
using Serilog;
-using SkiaSharp;
using Stylet;
namespace Artemis.UI
@@ -39,7 +36,7 @@ namespace Artemis.UI
protected override void Launch()
{
- _applicationStateManager = new ApplicationStateManager(Args);
+ _applicationStateManager = new ApplicationStateManager(Kernel, Args);
Core.Utilities.PrepareFirstLaunch();
ILogger logger = Kernel.Get();
@@ -94,10 +91,7 @@ namespace Artemis.UI
registrationService.RegisterInputProvider();
registrationService.RegisterControllers();
- Execute.OnUIThreadSync(() =>
- {
- registrationService.ApplyPreferredGraphicsContext();
- });
+ Execute.OnUIThreadSync(() => { registrationService.ApplyPreferredGraphicsContext(); });
// Initialize background services
Kernel.Get();
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
index 2060c520c..5055b02ac 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
@@ -17,8 +17,8 @@
-
+
@@ -42,15 +42,20 @@
-
+
-
+
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml
index 92bb2ad41..9948c56b9 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsView.xaml
@@ -12,7 +12,7 @@
d:DataContext="{d:DesignInstance devices:PluginSettingsViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
+
@@ -47,7 +47,7 @@
behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Parent.SearchPluginInput}"
behaviors:HighlightTermBehavior.Text="{Binding Plugin.Info.Name}"
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
- behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}"/>
+ behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}" />
+