fix warnings

This commit is contained in:
goat 2023-06-12 20:17:30 +02:00
parent faedf16d47
commit 0a829d304e
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
9 changed files with 266 additions and 189 deletions

View file

@ -327,6 +327,46 @@ internal class PluginInstallerWindow : Window, IDisposable
}); });
} }
/// <summary>
/// A continuation task that displays any errors received into the error modal.
/// </summary>
/// <param name="task">The previous task.</param>
/// <param name="state">An error message to be displayed.</param>
/// <returns>A value indicating whether to continue with the next task.</returns>
public bool DisplayErrorContinuation(Task task, object state)
{
if (task.IsFaulted)
{
var errorModalMessage = state as string;
foreach (var ex in task.Exception.InnerExceptions)
{
if (ex is PluginException)
{
Log.Error(ex, "Plugin installer threw an error");
#if DEBUG
if (!string.IsNullOrEmpty(ex.Message))
errorModalMessage += $"\n\n{ex.Message}";
#endif
}
else
{
Log.Error(ex, "Plugin installer threw an unexpected error");
#if DEBUG
if (!string.IsNullOrEmpty(ex.Message))
errorModalMessage += $"\n\n{ex.Message}";
#endif
}
}
this.ShowErrorModal(errorModalMessage);
return false;
}
return true;
}
private void DrawProgressOverlay() private void DrawProgressOverlay()
{ {
var pluginManager = Service<PluginManager>.Get(); var pluginManager = Service<PluginManager>.Get();
@ -2155,7 +2195,7 @@ internal class PluginInstallerWindow : Window, IDisposable
this.DrawSendFeedbackButton(plugin.Manifest, plugin.IsTesting); this.DrawSendFeedbackButton(plugin.Manifest, plugin.IsTesting);
} }
if (availablePluginUpdate != default && ! plugin.IsDev) if (availablePluginUpdate != default && !plugin.IsDev)
this.DrawUpdateSinglePluginButton(availablePluginUpdate); this.DrawUpdateSinglePluginButton(availablePluginUpdate);
ImGui.SameLine(); ImGui.SameLine();
@ -2914,46 +2954,6 @@ internal class PluginInstallerWindow : Window, IDisposable
private bool WasPluginSeen(string internalName) => private bool WasPluginSeen(string internalName) =>
Service<DalamudConfiguration>.Get().SeenPluginInternalName.Contains(internalName); Service<DalamudConfiguration>.Get().SeenPluginInternalName.Contains(internalName);
/// <summary>
/// A continuation task that displays any errors received into the error modal.
/// </summary>
/// <param name="task">The previous task.</param>
/// <param name="state">An error message to be displayed.</param>
/// <returns>A value indicating whether to continue with the next task.</returns>
public bool DisplayErrorContinuation(Task task, object state)
{
if (task.IsFaulted)
{
var errorModalMessage = state as string;
foreach (var ex in task.Exception.InnerExceptions)
{
if (ex is PluginException)
{
Log.Error(ex, "Plugin installer threw an error");
#if DEBUG
if (!string.IsNullOrEmpty(ex.Message))
errorModalMessage += $"\n\n{ex.Message}";
#endif
}
else
{
Log.Error(ex, "Plugin installer threw an unexpected error");
#if DEBUG
if (!string.IsNullOrEmpty(ex.Message))
errorModalMessage += $"\n\n{ex.Message}";
#endif
}
}
this.ShowErrorModal(errorModalMessage);
return false;
}
return true;
}
private Task ShowErrorModal(string message) private Task ShowErrorModal(string message)
{ {
this.errorModalMessage = message; this.errorModalMessage = message;

View file

@ -16,6 +16,9 @@ using Serilog;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller; namespace Dalamud.Interface.Internal.Windows.PluginInstaller;
/// <summary>
/// ImGui widget used to manage profiles.
/// </summary>
internal class ProfileManagerWidget internal class ProfileManagerWidget
{ {
private readonly PluginInstallerWindow installer; private readonly PluginInstallerWindow installer;
@ -25,11 +28,24 @@ internal class ProfileManagerWidget
private string pickerSearch = string.Empty; private string pickerSearch = string.Empty;
private string profileNameEdit = string.Empty; private string profileNameEdit = string.Empty;
/// <summary>
/// Initializes a new instance of the <see cref="ProfileManagerWidget"/> class.
/// </summary>
/// <param name="installer">The plugin installer.</param>
public ProfileManagerWidget(PluginInstallerWindow installer) public ProfileManagerWidget(PluginInstallerWindow installer)
{ {
this.installer = installer; this.installer = installer;
} }
private enum Mode
{
Overview,
EditSingleProfile,
}
/// <summary>
/// Draw this widget's contents.
/// </summary>
public void Draw() public void Draw()
{ {
switch (this.mode) switch (this.mode)
@ -44,6 +60,9 @@ internal class ProfileManagerWidget
} }
} }
/// <summary>
/// Reset the widget.
/// </summary>
public void Reset() public void Reset()
{ {
this.mode = Mode.Overview; this.mode = Mode.Overview;
@ -428,12 +447,6 @@ internal class ProfileManagerWidget
} }
} }
private enum Mode
{
Overview,
EditSingleProfile,
}
private static class Locs private static class Locs
{ {
public static string TooltipEnableDisable => public static string TooltipEnableDisable =>

View file

@ -816,137 +816,6 @@ internal partial class PluginManager : IDisposable, IServiceType
return plugin; return plugin;
} }
/// <summary>
/// Load a plugin.
/// </summary>
/// <param name="dllFile">The <see cref="FileInfo"/> associated with the main assembly of this plugin.</param>
/// <param name="manifest">The already loaded definition, if available.</param>
/// <param name="reason">The reason this plugin was loaded.</param>
/// <param name="isDev">If this plugin should support development features.</param>
/// <param name="isBoot">If this plugin is being loaded at boot.</param>
/// <param name="doNotLoad">Don't load the plugin, just don't do it.</param>
/// <returns>The loaded plugin.</returns>
private async Task<LocalPlugin> LoadPluginAsync(FileInfo dllFile, LocalPluginManifest? manifest, PluginLoadReason reason, bool isDev = false, bool isBoot = false, bool doNotLoad = false)
{
var name = manifest?.Name ?? dllFile.Name;
var loadPlugin = !doNotLoad;
LocalPlugin plugin;
if (manifest != null && manifest.InternalName == null)
{
Log.Error("{FileName}: Your manifest has no internal name set! Can't load this.", dllFile.FullName);
throw new Exception("No internal name");
}
if (isDev)
{
Log.Information($"Loading dev plugin {name}");
var devPlugin = new LocalDevPlugin(dllFile, manifest);
loadPlugin &= !isBoot || devPlugin.StartOnBoot;
var probablyInternalNameForThisPurpose = manifest?.InternalName ?? dllFile.Name;
var wantsInDefaultProfile =
this.profileManager.DefaultProfile.WantsPlugin(probablyInternalNameForThisPurpose);
if (wantsInDefaultProfile == false && devPlugin.StartOnBoot)
{
this.profileManager.DefaultProfile.AddOrUpdate(probablyInternalNameForThisPurpose, true, false);
}
else if (wantsInDefaultProfile == true && !devPlugin.StartOnBoot)
{
this.profileManager.DefaultProfile.AddOrUpdate(probablyInternalNameForThisPurpose, false, false);
}
plugin = devPlugin;
}
else
{
Log.Information($"Loading plugin {name}");
plugin = new LocalPlugin(dllFile, manifest);
}
#pragma warning disable CS0618
var defaultState = manifest?.Disabled != true && loadPlugin;
#pragma warning restore CS0618
// Need to do this here, so plugins that don't load are still added to the default profile
var wantToLoad = this.profileManager.GetWantState(plugin.Manifest.InternalName, defaultState);
if (loadPlugin)
{
try
{
if (wantToLoad && !plugin.IsOrphaned)
{
await plugin.LoadAsync(reason);
}
else
{
Log.Verbose($"{name} not loaded, wantToLoad:{wantToLoad} orphaned:{plugin.IsOrphaned}");
}
}
catch (InvalidPluginException)
{
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty, out _);
throw;
}
catch (BannedPluginException)
{
// Out of date plugins get added so they can be updated.
Log.Information($"Plugin was banned, adding anyways: {dllFile.Name}");
}
catch (Exception ex)
{
if (plugin.IsDev)
{
// Dev plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else if (plugin.IsOutdated)
{
// Out of date plugins get added, so they can be updated.
Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}");
}
else if (plugin.IsOrphaned)
{
// Orphaned plugins get added, so that users aren't confused.
Log.Information(ex, $"Plugin was orphaned, adding anyways: {dllFile.Name}");
}
else if (isBoot)
{
// During boot load, plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Regular plugin failed to load, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else if (!plugin.CheckPolicy())
{
// During boot load, plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Plugin not loaded due to policy, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else
{
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty, out _);
throw;
}
}
}
lock (this.pluginListLock)
{
this.InstalledPlugins = this.InstalledPlugins.Add(plugin);
}
return plugin;
}
/// <summary> /// <summary>
/// Remove a plugin. /// Remove a plugin.
/// </summary> /// </summary>
@ -1330,6 +1199,137 @@ internal partial class PluginManager : IDisposable, IServiceType
/// <returns>The calling plugin, or null.</returns> /// <returns>The calling plugin, or null.</returns>
public LocalPlugin? FindCallingPlugin() => this.FindCallingPlugin(new StackTrace()); public LocalPlugin? FindCallingPlugin() => this.FindCallingPlugin(new StackTrace());
/// <summary>
/// Load a plugin.
/// </summary>
/// <param name="dllFile">The <see cref="FileInfo"/> associated with the main assembly of this plugin.</param>
/// <param name="manifest">The already loaded definition, if available.</param>
/// <param name="reason">The reason this plugin was loaded.</param>
/// <param name="isDev">If this plugin should support development features.</param>
/// <param name="isBoot">If this plugin is being loaded at boot.</param>
/// <param name="doNotLoad">Don't load the plugin, just don't do it.</param>
/// <returns>The loaded plugin.</returns>
private async Task<LocalPlugin> LoadPluginAsync(FileInfo dllFile, LocalPluginManifest? manifest, PluginLoadReason reason, bool isDev = false, bool isBoot = false, bool doNotLoad = false)
{
var name = manifest?.Name ?? dllFile.Name;
var loadPlugin = !doNotLoad;
LocalPlugin plugin;
if (manifest != null && manifest.InternalName == null)
{
Log.Error("{FileName}: Your manifest has no internal name set! Can't load this.", dllFile.FullName);
throw new Exception("No internal name");
}
if (isDev)
{
Log.Information($"Loading dev plugin {name}");
var devPlugin = new LocalDevPlugin(dllFile, manifest);
loadPlugin &= !isBoot || devPlugin.StartOnBoot;
var probablyInternalNameForThisPurpose = manifest?.InternalName ?? dllFile.Name;
var wantsInDefaultProfile =
this.profileManager.DefaultProfile.WantsPlugin(probablyInternalNameForThisPurpose);
if (wantsInDefaultProfile == false && devPlugin.StartOnBoot)
{
this.profileManager.DefaultProfile.AddOrUpdate(probablyInternalNameForThisPurpose, true, false);
}
else if (wantsInDefaultProfile == true && !devPlugin.StartOnBoot)
{
this.profileManager.DefaultProfile.AddOrUpdate(probablyInternalNameForThisPurpose, false, false);
}
plugin = devPlugin;
}
else
{
Log.Information($"Loading plugin {name}");
plugin = new LocalPlugin(dllFile, manifest);
}
#pragma warning disable CS0618
var defaultState = manifest?.Disabled != true && loadPlugin;
#pragma warning restore CS0618
// Need to do this here, so plugins that don't load are still added to the default profile
var wantToLoad = this.profileManager.GetWantState(plugin.Manifest.InternalName, defaultState);
if (loadPlugin)
{
try
{
if (wantToLoad && !plugin.IsOrphaned)
{
await plugin.LoadAsync(reason);
}
else
{
Log.Verbose($"{name} not loaded, wantToLoad:{wantToLoad} orphaned:{plugin.IsOrphaned}");
}
}
catch (InvalidPluginException)
{
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty, out _);
throw;
}
catch (BannedPluginException)
{
// Out of date plugins get added so they can be updated.
Log.Information($"Plugin was banned, adding anyways: {dllFile.Name}");
}
catch (Exception ex)
{
if (plugin.IsDev)
{
// Dev plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else if (plugin.IsOutdated)
{
// Out of date plugins get added, so they can be updated.
Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}");
}
else if (plugin.IsOrphaned)
{
// Orphaned plugins get added, so that users aren't confused.
Log.Information(ex, $"Plugin was orphaned, adding anyways: {dllFile.Name}");
}
else if (isBoot)
{
// During boot load, plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Regular plugin failed to load, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else if (!plugin.CheckPolicy())
{
// During boot load, plugins always get added to the list so they can be fiddled with in the UI
Log.Information(ex, $"Plugin not loaded due to policy, adding anyways: {dllFile.Name}");
// NOTE(goat): This can't work - plugins don't "unload" if they fail to load.
// plugin.Disable(); // Disable here, otherwise you can't enable+load later
}
else
{
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty, out _);
throw;
}
}
}
lock (this.pluginListLock)
{
this.InstalledPlugins = this.InstalledPlugins.Add(plugin);
}
return plugin;
}
private void DetectAvailablePluginUpdates() private void DetectAvailablePluginUpdates()
{ {
var updatablePlugins = new List<AvailablePluginUpdate>(); var updatablePlugins = new List<AvailablePluginUpdate>();

View file

@ -61,6 +61,13 @@ internal class ProfileCommandHandler : IServiceType, IDisposable
this.framework.Update += this.FrameworkOnUpdate; this.framework.Update += this.FrameworkOnUpdate;
} }
private enum ProfileOp
{
Enable,
Disable,
Toggle,
}
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose()
{ {
@ -166,11 +173,4 @@ internal class ProfileCommandHandler : IServiceType, IDisposable
return name; return name;
} }
private enum ProfileOp
{
Enable,
Disable,
Toggle,
}
} }

View file

@ -165,7 +165,7 @@ internal class ProfileManager : IServiceType
/// <summary> /// <summary>
/// Go through all profiles and plugins, and enable/disable plugins they want active. /// Go through all profiles and plugins, and enable/disable plugins they want active.
/// This will block until all plugins have been loaded/reloaded! /// This will block until all plugins have been loaded/reloaded.
/// </summary> /// </summary>
public void ApplyAllWantStates() public void ApplyAllWantStates()
{ {

View file

@ -5,14 +5,29 @@ using Newtonsoft.Json;
namespace Dalamud.Plugin.Internal.Profiles; namespace Dalamud.Plugin.Internal.Profiles;
/// <summary>
/// Class representing a profile.
/// </summary>
public abstract class ProfileModel public abstract class ProfileModel
{ {
/// <summary>
/// Gets or sets the ID of the profile.
/// </summary>
[JsonProperty("id")] [JsonProperty("id")]
public Guid Guid { get; set; } = Guid.Empty; public Guid Guid { get; set; } = Guid.Empty;
/// <summary>
/// Gets or sets the name of the profile.
/// </summary>
[JsonProperty("n")] [JsonProperty("n")]
public string Name { get; set; } = "New Profile"; public string Name { get; set; } = "New Profile";
/// <summary>
/// Deserialize a profile into a model.
/// </summary>
/// <param name="model">The string to decompress.</param>
/// <returns>The parsed model.</returns>
/// <exception cref="ArgumentException">Thrown when the parsed string is not a valid profile.</exception>
public static ProfileModel? Deserialize(string model) public static ProfileModel? Deserialize(string model)
{ {
var json = Util.DecompressString(Convert.FromBase64String(model.Substring(3))); var json = Util.DecompressString(Convert.FromBase64String(model.Substring(3)));
@ -23,6 +38,11 @@ public abstract class ProfileModel
throw new ArgumentException("Was not a compressed style model."); throw new ArgumentException("Was not a compressed style model.");
} }
/// <summary>
/// Serialize this model into a string usable for sharing.
/// </summary>
/// <returns>The serialized representation of the model.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when an unsupported model is serialized.</exception>
public string Serialize() public string Serialize()
{ {
string prefix; string prefix;

View file

@ -1,27 +1,55 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Dalamud.Plugin.Internal.Profiles; namespace Dalamud.Plugin.Internal.Profiles;
/// <summary>
/// Version 1 of the profile model.
/// </summary>
public class ProfileModelV1 : ProfileModel public class ProfileModelV1 : ProfileModel
{ {
/// <summary>
/// Gets the prefix of this version.
/// </summary>
public static string SerializedPrefix => "DP1"; public static string SerializedPrefix => "DP1";
/// <summary>
/// Gets or sets a value indicating whether or not this profile should always be enabled at boot.
/// </summary>
[JsonProperty("b")] [JsonProperty("b")]
public bool AlwaysEnableOnBoot { get; set; } = false; public bool AlwaysEnableOnBoot { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether or not this profile is currently enabled.
/// </summary>
[JsonProperty("e")] [JsonProperty("e")]
public bool IsEnabled { get; set; } = false; public bool IsEnabled { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating this profile's color.
/// </summary>
[JsonProperty("c")] [JsonProperty("c")]
public uint Color { get; set; } public uint Color { get; set; }
/// <summary>
/// Gets or sets the list of plugins in this profile.
/// </summary>
public List<ProfileModelV1Plugin> Plugins { get; set; } = new(); public List<ProfileModelV1Plugin> Plugins { get; set; } = new();
/// <summary>
/// Class representing a single plugin in a profile.
/// </summary>
public class ProfileModelV1Plugin public class ProfileModelV1Plugin
{ {
public string InternalName { get; set; } /// <summary>
/// Gets or sets the internal name of the plugin.
/// </summary>
public string? InternalName { get; set; }
/// <summary>
/// Gets or sets a value indicating whether or not this entry is enabled.
/// </summary>
public bool IsEnabled { get; set; } public bool IsEnabled { get; set; }
} }
} }

View file

@ -1,14 +1,28 @@
namespace Dalamud.Plugin.Internal.Profiles; namespace Dalamud.Plugin.Internal.Profiles;
/// <summary>
/// Class representing a single plugin in a profile.
/// </summary>
internal class ProfilePluginEntry internal class ProfilePluginEntry
{ {
/// <summary>
/// Initializes a new instance of the <see cref="ProfilePluginEntry"/> class.
/// </summary>
/// <param name="internalName">The internal name of the plugin.</param>
/// <param name="state">A value indicating whether or not this entry is enabled.</param>
public ProfilePluginEntry(string internalName, bool state) public ProfilePluginEntry(string internalName, bool state)
{ {
this.InternalName = internalName; this.InternalName = internalName;
this.IsEnabled = state; this.IsEnabled = state;
} }
/// <summary>
/// Gets the internal name of the plugin.
/// </summary>
public string InternalName { get; } public string InternalName { get; }
/// <summary>
/// Gets a value indicating whether or not this entry is enabled.
/// </summary>
public bool IsEnabled { get; } public bool IsEnabled { get; }
} }

View file

@ -136,7 +136,9 @@ internal class LocalPlugin : IDisposable
this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile); this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile);
if (this.disabledFile.Exists) if (this.disabledFile.Exists)
{ {
#pragma warning disable CS0618
this.Manifest.Disabled = true; this.Manifest.Disabled = true;
#pragma warning restore CS0618
this.disabledFile.Delete(); this.disabledFile.Delete();
} }
@ -627,9 +629,9 @@ internal class LocalPlugin : IDisposable
var manifest = LocalPluginManifest.GetManifestFile(this.DllFile); var manifest = LocalPluginManifest.GetManifestFile(this.DllFile);
if (manifest.Exists) if (manifest.Exists)
{ {
//var isDisabled = this.IsDisabled; // saving the internal state because it could have been deleted // var isDisabled = this.IsDisabled; // saving the internal state because it could have been deleted
this.Manifest = LocalPluginManifest.Load(manifest); this.Manifest = LocalPluginManifest.Load(manifest);
//this.Manifest.Disabled = isDisabled; // this.Manifest.Disabled = isDisabled;
this.SaveManifest(); this.SaveManifest();
} }