mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
238 lines
8.4 KiB
C#
238 lines
8.4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using Artemis.Core;
|
|
using Artemis.Core.DataModelExpansions;
|
|
using Artemis.Core.DeviceProviders;
|
|
using Artemis.Core.LayerBrushes;
|
|
using Artemis.Core.LayerEffects;
|
|
using Artemis.Core.Modules;
|
|
using Artemis.Core.Services;
|
|
using Artemis.UI.Exceptions;
|
|
using Artemis.UI.Shared.Services;
|
|
using MaterialDesignThemes.Wpf;
|
|
using Ninject;
|
|
using Ninject.Parameters;
|
|
using Serilog;
|
|
using Stylet;
|
|
using Module = Artemis.Core.Modules.Module;
|
|
|
|
namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|
{
|
|
public class PluginSettingsViewModel : PropertyChangedBase
|
|
{
|
|
private readonly IDialogService _dialogService;
|
|
private readonly ILogger _logger;
|
|
private readonly IPluginService _pluginService;
|
|
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
|
private readonly IWindowManager _windowManager;
|
|
private bool _enabling;
|
|
private Plugin _plugin;
|
|
private PluginInfo _pluginInfo;
|
|
|
|
public PluginSettingsViewModel(Plugin plugin,
|
|
ILogger logger,
|
|
IWindowManager windowManager,
|
|
IDialogService dialogService,
|
|
IPluginService pluginService,
|
|
ISnackbarMessageQueue snackbarMessageQueue)
|
|
{
|
|
Plugin = plugin;
|
|
PluginInfo = plugin.PluginInfo;
|
|
|
|
_logger = logger;
|
|
_windowManager = windowManager;
|
|
_dialogService = dialogService;
|
|
_pluginService = pluginService;
|
|
_snackbarMessageQueue = snackbarMessageQueue;
|
|
}
|
|
|
|
public Plugin Plugin
|
|
{
|
|
get => _plugin;
|
|
set => SetAndNotify(ref _plugin, value);
|
|
}
|
|
|
|
public PluginInfo PluginInfo
|
|
{
|
|
get => _pluginInfo;
|
|
set => SetAndNotify(ref _pluginInfo, value);
|
|
}
|
|
|
|
public bool Enabling
|
|
{
|
|
get => _enabling;
|
|
set => SetAndNotify(ref _enabling, value);
|
|
}
|
|
|
|
public PackIconKind Icon => GetIconKind();
|
|
public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name;
|
|
public bool CanOpenSettings => IsEnabled && Plugin.ConfigurationDialog != null;
|
|
public bool DisplayLoadFailed => !Enabling && PluginInfo.LoadException != null;
|
|
public bool RequiresRestart => Plugin.Enabled && !PluginInfo.Enabled;
|
|
|
|
public bool IsEnabled
|
|
{
|
|
get => Plugin.PluginInfo.Enabled;
|
|
set => Task.Run(() => UpdateEnabled(value));
|
|
}
|
|
|
|
public void OpenSettings()
|
|
{
|
|
PluginConfigurationDialog configurationViewModel = Plugin.ConfigurationDialog;
|
|
if (configurationViewModel == null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
// Limit to one constructor, there's no need to have more and it complicates things anyway
|
|
ConstructorInfo[] constructors = configurationViewModel.Type.GetConstructors();
|
|
if (constructors.Length != 1)
|
|
throw new ArtemisUIException("Plugin configuration dialogs must have exactly one constructor");
|
|
|
|
ParameterInfo pluginParameter = constructors.First().GetParameters().First(p => typeof(Plugin).IsAssignableFrom(p.ParameterType));
|
|
ConstructorArgument plugin = new ConstructorArgument(pluginParameter.Name, Plugin);
|
|
PluginConfigurationViewModel viewModel = (PluginConfigurationViewModel) PluginInfo.Kernel.Get(configurationViewModel.Type, plugin);
|
|
_windowManager.ShowDialog(new PluginSettingsWindowViewModel(viewModel, Icon));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_dialogService.ShowExceptionDialog("An exception occured while trying to show the plugin's settings window", e);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public void ShowLogsFolder()
|
|
{
|
|
try
|
|
{
|
|
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_dialogService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
|
|
}
|
|
}
|
|
|
|
public void ShowLoadException()
|
|
{
|
|
if (PluginInfo.LoadException == null)
|
|
return;
|
|
|
|
_dialogService.ShowExceptionDialog("The plugin failed to load: " + PluginInfo.LoadException.Message, PluginInfo.LoadException);
|
|
}
|
|
|
|
public async Task Restart()
|
|
{
|
|
_logger.Debug("Restarting for device provider disable {pluginInfo}", Plugin.PluginInfo);
|
|
|
|
// Give the logger a chance to write, might not always be enough but oh well
|
|
await Task.Delay(500);
|
|
Core.Utilities.Shutdown(2, true);
|
|
}
|
|
|
|
private PackIconKind GetIconKind()
|
|
{
|
|
if (PluginInfo.Icon != null)
|
|
{
|
|
bool parsedIcon = Enum.TryParse<PackIconKind>(PluginInfo.Icon, true, out PackIconKind iconEnum);
|
|
if (parsedIcon)
|
|
return iconEnum;
|
|
}
|
|
|
|
switch (Plugin)
|
|
{
|
|
case BaseDataModelExpansion _:
|
|
return PackIconKind.TableAdd;
|
|
case DeviceProvider _:
|
|
return PackIconKind.Devices;
|
|
case ProfileModule _:
|
|
return PackIconKind.VectorRectangle;
|
|
case Module _:
|
|
return PackIconKind.GearBox;
|
|
case LayerBrushProvider _:
|
|
return PackIconKind.Brush;
|
|
case LayerEffectProvider _:
|
|
return PackIconKind.AutoAwesome;
|
|
}
|
|
|
|
return PackIconKind.Plugin;
|
|
}
|
|
|
|
private async Task UpdateEnabled(bool enable)
|
|
{
|
|
if (IsEnabled == enable)
|
|
{
|
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
|
return;
|
|
}
|
|
|
|
if (!enable && Plugin is DeviceProvider)
|
|
{
|
|
await DisableDeviceProvider();
|
|
return;
|
|
}
|
|
|
|
if (enable)
|
|
{
|
|
Enabling = true;
|
|
NotifyOfPropertyChange(nameof(DisplayLoadFailed));
|
|
|
|
try
|
|
{
|
|
_pluginService.EnablePlugin(Plugin);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_snackbarMessageQueue.Enqueue($"Failed to enable plugin {PluginInfo.Name}\r\n{e.Message}", "VIEW LOGS", ShowLogsFolder);
|
|
}
|
|
finally
|
|
{
|
|
Enabling = false;
|
|
}
|
|
}
|
|
else
|
|
_pluginService.DisablePlugin(Plugin);
|
|
|
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
|
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
|
NotifyOfPropertyChange(nameof(RequiresRestart));
|
|
NotifyOfPropertyChange(nameof(DisplayLoadFailed));
|
|
}
|
|
|
|
private async Task DisableDeviceProvider()
|
|
{
|
|
bool restart = false;
|
|
|
|
// If any plugin already requires a restart, don't ask the user again
|
|
bool restartQueued = _pluginService.GetAllPluginInfo().Any(p => p.Instance != null && !p.Enabled && p.Instance.Enabled);
|
|
// If the plugin isn't enabled (load failed), it can be disabled without a restart
|
|
if (!restartQueued && Plugin.Enabled)
|
|
{
|
|
restart = await _dialogService.ShowConfirmDialog(
|
|
"Disable device provider",
|
|
"You are disabling a device provider, Artemis has to restart to \r\nfully disable this type of plugin",
|
|
"Restart now",
|
|
"Restart later"
|
|
);
|
|
}
|
|
|
|
_pluginService.DisablePlugin(Plugin);
|
|
if (restart)
|
|
{
|
|
_logger.Debug("Restarting for device provider disable {pluginInfo}", Plugin.PluginInfo);
|
|
|
|
// Give the logger a chance to write, might not always be enough but oh well
|
|
await Task.Delay(500);
|
|
Core.Utilities.Shutdown(2, true);
|
|
}
|
|
|
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
|
NotifyOfPropertyChange(nameof(RequiresRestart));
|
|
NotifyOfPropertyChange(nameof(DisplayLoadFailed));
|
|
}
|
|
}
|
|
} |