chore: better UI for disabled plugins, plugin toggles

This commit is contained in:
goat 2022-07-16 00:19:04 +02:00
parent 30b1a4d383
commit 8863eb9a20
No known key found for this signature in database
GPG key ID: 7773BB5B43BA52E5
2 changed files with 159 additions and 49 deletions

View file

@ -54,6 +54,7 @@ namespace Dalamud.Interface.Internal.Windows
private readonly ConcurrentDictionary<string, TextureWrap?[]?> pluginImagesMap = new(); private readonly ConcurrentDictionary<string, TextureWrap?[]?> pluginImagesMap = new();
private readonly Task<TextureWrap> emptyTextureTask; private readonly Task<TextureWrap> emptyTextureTask;
private readonly Task<TextureWrap> disabledIconTask;
private readonly Task<TextureWrap> defaultIconTask; private readonly Task<TextureWrap> defaultIconTask;
private readonly Task<TextureWrap> troubleIconTask; private readonly Task<TextureWrap> troubleIconTask;
private readonly Task<TextureWrap> updateIconTask; private readonly Task<TextureWrap> updateIconTask;
@ -71,6 +72,7 @@ namespace Dalamud.Interface.Internal.Windows
this.emptyTextureTask = imwst.ContinueWith(task => task.Result.Manager.LoadImageRaw(new byte[64], 8, 8, 4)!); this.emptyTextureTask = imwst.ContinueWith(task => task.Result.Manager.LoadImageRaw(new byte[64], 8, 8, 4)!);
this.defaultIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "defaultIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.defaultIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "defaultIcon.png"))) ?? this.emptyTextureTask).Unwrap();
this.disabledIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "disabledIcon.png"))) ?? this.emptyTextureTask).Unwrap();
this.troubleIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "troubleIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.troubleIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "troubleIcon.png"))) ?? this.emptyTextureTask).Unwrap();
this.updateIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "updateIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.updateIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "updateIcon.png"))) ?? this.emptyTextureTask).Unwrap();
this.installedIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "installedIcon.png"))) ?? this.emptyTextureTask).Unwrap(); this.installedIconTask = imwst.ContinueWith(task => TaskWrapIfNonNull(task.Result.Manager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "installedIcon.png"))) ?? this.emptyTextureTask).Unwrap();
@ -91,6 +93,13 @@ namespace Dalamud.Interface.Internal.Windows
? this.emptyTextureTask.Result ? this.emptyTextureTask.Result
: this.emptyTextureTask.GetAwaiter().GetResult(); : this.emptyTextureTask.GetAwaiter().GetResult();
/// <summary>
/// Gets the default plugin icon.
/// </summary>
public TextureWrap DisabledIcon => this.disabledIconTask.IsCompleted
? this.disabledIconTask.Result
: this.disabledIconTask.GetAwaiter().GetResult();
/// <summary> /// <summary>
/// Gets the default plugin icon. /// Gets the default plugin icon.
/// </summary> /// </summary>

View file

@ -83,6 +83,9 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
private OperationStatus installStatus = OperationStatus.Idle; private OperationStatus installStatus = OperationStatus.Idle;
private OperationStatus updateStatus = OperationStatus.Idle; private OperationStatus updateStatus = OperationStatus.Idle;
private OperationStatus enableDisableStatus = OperationStatus.Idle;
private LoadingIndicatorKind loadingIndicatorKind = LoadingIndicatorKind.Unknown;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PluginInstallerWindow"/> class. /// Initializes a new instance of the <see cref="PluginInstallerWindow"/> class.
@ -130,6 +133,17 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
Complete, Complete,
} }
private enum LoadingIndicatorKind
{
Unknown,
EnablingSingle,
DisablingSingle,
UpdatingSingle,
UpdatingAll,
Installing,
Manager,
}
private enum PluginSortKind private enum PluginSortKind
{ {
Alphabetical, Alphabetical,
@ -139,6 +153,10 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
NotInstalled, NotInstalled,
} }
private bool AnyOperationInProgress => this.installStatus == OperationStatus.InProgress ||
this.updateStatus == OperationStatus.InProgress ||
this.enableDisableStatus == OperationStatus.InProgress;
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose()
{ {
@ -184,6 +202,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
this.DrawFooter(); this.DrawFooter();
this.DrawErrorModal(); this.DrawErrorModal();
this.DrawFeedbackModal(); this.DrawFeedbackModal();
this.DrawProgressOverlay();
} }
/// <summary> /// <summary>
@ -194,6 +213,69 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
this.imageCache.ClearIconCache(); this.imageCache.ClearIconCache();
} }
private void DrawProgressOverlay()
{
var pluginManager = Service<PluginManager>.Get();
var isWaitingManager = !pluginManager.PluginsReady ||
!pluginManager.ReposReady;
var isLoading = this.AnyOperationInProgress ||
isWaitingManager;
if (isWaitingManager)
this.loadingIndicatorKind = LoadingIndicatorKind.Manager;
if (!isLoading)
return;
ImGui.SetCursorPos(Vector2.Zero);
var windowSize = ImGui.GetWindowSize();
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
ImGui.PushStyleVar(ImGuiStyleVar.CellPadding, Vector2.Zero);;
ImGui.PushStyleVar(ImGuiStyleVar.ChildBorderSize, 0);
ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 0);
ImGui.SetNextWindowBgAlpha(0.8f);
if (ImGui.BeginChild("###installerLoadingFrame", new Vector2(-1, -1), false))
{
ImGui.SetCursorPosY(windowSize.Y / 2);
switch (this.loadingIndicatorKind)
{
case LoadingIndicatorKind.Unknown:
ImGuiHelpers.CenteredText("Doing something, not sure what!");
break;
case LoadingIndicatorKind.EnablingSingle:
ImGuiHelpers.CenteredText("Enabling plugin...");
break;
case LoadingIndicatorKind.DisablingSingle:
ImGuiHelpers.CenteredText("Disabling plugin...");
break;
case LoadingIndicatorKind.UpdatingSingle:
ImGuiHelpers.CenteredText("Updating plugin...");
break;
case LoadingIndicatorKind.UpdatingAll:
ImGuiHelpers.CenteredText("Updating plugins...");
break;
case LoadingIndicatorKind.Installing:
ImGuiHelpers.CenteredText("Installing plugin...");
break;
case LoadingIndicatorKind.Manager:
ImGuiHelpers.CenteredText("Loading repositories and plugins...");
break;
default:
throw new ArgumentOutOfRangeException();
}
ImGui.EndChild();
}
ImGui.PopStyleVar(5);
}
private void DrawHeader() private void DrawHeader()
{ {
var style = ImGui.GetStyle(); var style = ImGui.GetStyle();
@ -336,6 +418,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
if (ImGui.Button(Locs.FooterButton_UpdatePlugins)) if (ImGui.Button(Locs.FooterButton_UpdatePlugins))
{ {
this.updateStatus = OperationStatus.InProgress; this.updateStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.UpdatingAll;
Task.Run(() => pluginManager.UpdatePluginsAsync()) Task.Run(() => pluginManager.UpdatePluginsAsync())
.ContinueWith(task => .ContinueWith(task =>
@ -1104,6 +1187,8 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
ImGui.SetCursorPos(startCursor); ImGui.SetCursorPos(startCursor);
var pluginDisabled = plugin is { IsDisabled: true };
var iconSize = ImGuiHelpers.ScaledVector2(64, 64); var iconSize = ImGuiHelpers.ScaledVector2(64, 64);
var cursorBeforeImage = ImGui.GetCursorPos(); var cursorBeforeImage = ImGui.GetCursorPos();
var rectOffset = ImGui.GetWindowContentRegionMin() + ImGui.GetWindowPos(); var rectOffset = ImGui.GetWindowContentRegionMin() + ImGui.GetWindowPos();
@ -1116,7 +1201,18 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
iconTex = cachedIconTex; iconTex = cachedIconTex;
} }
if (pluginDisabled)
{
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
}
ImGui.Image(iconTex.ImGuiHandle, iconSize); ImGui.Image(iconTex.ImGuiHandle, iconSize);
if (pluginDisabled)
{
ImGui.PopStyleVar();
}
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetCursorPos(cursorBeforeImage); ImGui.SetCursorPos(cursorBeforeImage);
} }
@ -1125,8 +1221,10 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
if (updateAvailable) if (updateAvailable)
ImGui.Image(this.imageCache.UpdateIcon.ImGuiHandle, iconSize); ImGui.Image(this.imageCache.UpdateIcon.ImGuiHandle, iconSize);
else if (trouble) else if (trouble && !pluginDisabled)
ImGui.Image(this.imageCache.TroubleIcon.ImGuiHandle, iconSize); ImGui.Image(this.imageCache.TroubleIcon.ImGuiHandle, iconSize);
else if (pluginDisabled)
ImGui.Image(this.imageCache.DisabledIcon.ImGuiHandle, iconSize);
else if (isLoaded && isThirdParty) else if (isLoaded && isThirdParty)
ImGui.Image(this.imageCache.ThirdInstalledIcon.ImGuiHandle, iconSize); ImGui.Image(this.imageCache.ThirdInstalledIcon.ImGuiHandle, iconSize);
else if (isThirdParty) else if (isThirdParty)
@ -1357,6 +1455,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
if (ImGui.Button($"{buttonText}##{buttonText}{index}")) if (ImGui.Button($"{buttonText}##{buttonText}{index}"))
{ {
this.installStatus = OperationStatus.InProgress; this.installStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.Installing;
Task.Run(() => pluginManager.InstallPluginAsync(manifest, useTesting, PluginLoadReason.Installer)) Task.Run(() => pluginManager.InstallPluginAsync(manifest, useTesting, PluginLoadReason.Installer))
.ContinueWith(task => .ContinueWith(task =>
@ -1450,8 +1549,6 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{ {
var configuration = Service<DalamudConfiguration>.Get(); var configuration = Service<DalamudConfiguration>.Get();
var commandManager = Service<CommandManager>.Get(); var commandManager = Service<CommandManager>.Get();
var pluginManager = Service<PluginManager>.Get();
var startInfo = Service<DalamudStartInfo>.Get();
var trouble = false; var trouble = false;
@ -1697,10 +1794,8 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
private void DrawPluginControlButton(LocalPlugin plugin) private void DrawPluginControlButton(LocalPlugin plugin)
{ {
var configuration = Service<DalamudConfiguration>.Get();
var notifications = Service<NotificationManager>.Get(); var notifications = Service<NotificationManager>.Get();
var pluginManager = Service<PluginManager>.Get(); var pluginManager = Service<PluginManager>.Get();
var startInfo = Service<DalamudStartInfo>.Get();
// Disable everything if the updater is running or another plugin is operating // Disable everything if the updater is running or another plugin is operating
var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress; var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress;
@ -1714,91 +1809,90 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
// Disable everything if the plugin failed to load // Disable everything if the plugin failed to load
disabled = disabled || plugin.State == PluginState.LoadError || plugin.State == PluginState.DependencyResolutionFailed; disabled = disabled || plugin.State == PluginState.LoadError || plugin.State == PluginState.DependencyResolutionFailed;
if (plugin.State == PluginState.Loading || plugin.State == PluginState.Unloading) // Disable everything if we're working
disabled = disabled || plugin.State == PluginState.Loading || plugin.State == PluginState.Unloading;
var toggleId = plugin.Manifest.InternalName;
var isLoadedAndUnloadable = plugin.State == PluginState.Loaded ||
plugin.State == PluginState.DependencyResolutionFailed;
if (plugin.State == PluginState.UnloadError)
{ {
ImGuiComponents.DisabledButton(Locs.PluginButton_Working); ImGuiComponents.DisabledButton(FontAwesomeIcon.Frown);
if (ImGui.IsItemHovered())
ImGui.SetTooltip(Locs.PluginButtonToolTip_UnloadFailed);
} }
else if (plugin.State == PluginState.Loaded || plugin.State == PluginState.LoadError || plugin.State == PluginState.DependencyResolutionFailed) else if (disabled)
{ {
if (pluginManager.SafeMode) ImGuiComponents.DisabledToggleButton(toggleId, isLoadedAndUnloadable);
}
else
{
if (ImGuiComponents.ToggleButton(toggleId, ref isLoadedAndUnloadable))
{ {
ImGuiComponents.DisabledButton(Locs.PluginButton_SafeMode); if (!isLoadedAndUnloadable)
}
else if (disabled)
{
ImGuiComponents.DisabledButton(Locs.PluginButton_Disable);
}
else
{
if (ImGui.Button(Locs.PluginButton_Disable))
{ {
this.enableDisableStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.DisablingSingle;
Task.Run(() => Task.Run(() =>
{ {
var unloadTask = Task.Run(() => plugin.UnloadAsync()) var unloadTask = Task.Run(() => plugin.UnloadAsync())
.ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_UnloadFail(plugin.Name)); .ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_UnloadFail(plugin.Name));
unloadTask.Wait(); unloadTask.Wait();
if (!unloadTask.Result) if (!unloadTask.Result)
return; return;
var disableTask = Task.Run(() => plugin.Disable()) var disableTask = Task.Run(() => plugin.Disable())
.ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_DisableFail(plugin.Name)); .ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_DisableFail(plugin.Name));
disableTask.Wait(); disableTask.Wait();
this.enableDisableStatus = OperationStatus.Complete;
if (!disableTask.Result) if (!disableTask.Result)
return; return;
/*if (!plugin.IsDev)
{
pluginManager.RemovePlugin(plugin);
}*/
notifications.AddNotification(Locs.Notifications_PluginDisabled(plugin.Manifest.Name), Locs.Notifications_PluginDisabledTitle, NotificationType.Success); notifications.AddNotification(Locs.Notifications_PluginDisabled(plugin.Manifest.Name), Locs.Notifications_PluginDisabledTitle, NotificationType.Success);
}); });
} }
} else
if (plugin.State == PluginState.Loaded)
{
// Only if the plugin isn't broken.
this.DrawOpenPluginSettingsButton(plugin);
}
}
else if (plugin.State == PluginState.Unloaded)
{
if (disabled)
{
ImGuiComponents.DisabledButton(Locs.PluginButton_Load);
}
else
{
if (ImGui.Button(Locs.PluginButton_Load))
{ {
this.enableDisableStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.EnablingSingle;
Task.Run(() => Task.Run(() =>
{ {
var enableTask = Task.Run(() => plugin.Enable()) var enableTask = Task.Run(() => plugin.Enable())
.ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_EnableFail(plugin.Name)); .ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_EnableFail(plugin.Name));
enableTask.Wait(); enableTask.Wait();
if (!enableTask.Result) if (!enableTask.Result)
return; return;
var loadTask = Task.Run(() => plugin.LoadAsync(PluginLoadReason.Installer)) var loadTask = Task.Run(() => plugin.LoadAsync(PluginLoadReason.Installer))
.ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_LoadFail(plugin.Name)); .ContinueWith(this.DisplayErrorContinuation, Locs.ErrorModal_LoadFail(plugin.Name));
loadTask.Wait(); loadTask.Wait();
this.enableDisableStatus = OperationStatus.Complete;
if (!loadTask.Result) if (!loadTask.Result)
return; return;
notifications.AddNotification(Locs.Notifications_PluginEnabled(plugin.Manifest.Name), Locs.Notifications_PluginEnabledTitle, NotificationType.Success);
}); });
} }
} }
} }
else if (plugin.State == PluginState.UnloadError)
{
ImGuiComponents.DisabledButton(FontAwesomeIcon.Frown);
if (ImGui.IsItemHovered()) ImGui.SameLine();
ImGui.SetTooltip(Locs.PluginButtonToolTip_UnloadFailed); ImGuiHelpers.ScaledDummy(15, 0);
if (plugin.State == PluginState.Loaded)
{
// Only if the plugin isn't broken.
this.DrawOpenPluginSettingsButton(plugin);
} }
} }
@ -1811,6 +1905,7 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
if (ImGuiComponents.IconButton(FontAwesomeIcon.Download)) if (ImGuiComponents.IconButton(FontAwesomeIcon.Download))
{ {
this.installStatus = OperationStatus.InProgress; this.installStatus = OperationStatus.InProgress;
this.loadingIndicatorKind = LoadingIndicatorKind.UpdatingSingle;
Task.Run(async () => await pluginManager.UpdateSinglePluginAsync(update, true, false)) Task.Run(async () => await pluginManager.UpdateSinglePluginAsync(update, true, false))
.ContinueWith(task => .ContinueWith(task =>
@ -1879,6 +1974,8 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
private void DrawDevPluginButtons(LocalPlugin localPlugin) private void DrawDevPluginButtons(LocalPlugin localPlugin)
{ {
ImGui.SameLine();
var configuration = Service<DalamudConfiguration>.Get(); var configuration = Service<DalamudConfiguration>.Get();
if (localPlugin is LocalDevPlugin plugin) if (localPlugin is LocalDevPlugin plugin)
@ -2425,6 +2522,10 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller
public static string Notifications_PluginDisabled(string name) => Loc.Localize("NotificationsPluginDisabled", "'{0}' was disabled.").Format(name); public static string Notifications_PluginDisabled(string name) => Loc.Localize("NotificationsPluginDisabled", "'{0}' was disabled.").Format(name);
public static string Notifications_PluginEnabledTitle => Loc.Localize("NotificationsPluginEnabledTitle", "Plugin enabled!");
public static string Notifications_PluginEnabled(string name) => Loc.Localize("NotificationsPluginEnabled", "'{0}' was enabled.").Format(name);
#endregion #endregion
#region Footer #region Footer